View Javadoc
1   /*
2    * Copyright (c) 2002-2025 Gargoyle Software Inc.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    * https://www.apache.org/licenses/LICENSE-2.0
8    *
9    * Unless required by applicable law or agreed to in writing, software
10   * distributed under the License is distributed on an "AS IS" BASIS,
11   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12   * See the License for the specific language governing permissions and
13   * limitations under the License.
14   */
15  package org.htmlunit.javascript.host;
16  
17  import java.util.Set;
18  
19  import org.htmlunit.WebDriverTestCase;
20  import org.htmlunit.junit.BrowserRunner;
21  import org.htmlunit.junit.annotation.Alerts;
22  import org.junit.Test;
23  import org.junit.runner.RunWith;
24  
25  /**
26   * Tests for {@link Set}.
27   *
28   * @author Ahmed Ashour
29   * @author Ronald Brill
30   */
31  @RunWith(BrowserRunner.class)
32  public class SetTest extends WebDriverTestCase {
33  
34      /**
35       * @throws Exception if the test fails
36       */
37      @Test
38      @Alerts({"3", "true"})
39      public void has() throws Exception {
40          final String html = DOCTYPE_HTML
41              + "<html>\n"
42              + "<head>\n"
43              + "<script>\n"
44              + LOG_TITLE_FUNCTION
45              + "  function test() {\n"
46              + "    var myArray = ['value1', 'value2', 'value3'];\n"
47              + "    var mySet = new Set(myArray);\n"
48              + "    mySet.add('value1');\n"
49              + "    log(mySet.size);\n"
50              + "    log(mySet.has('value2'));\n"
51              + "  }\n"
52              + "</script>\n"
53              + "</head>\n"
54              + "<body onload='test()'>\n"
55              + "</body></html>";
56  
57          loadPageVerifyTitle2(html);
58      }
59  
60      /**
61       * @throws Exception if the test fails
62       */
63      @Test
64      @Alerts({"function values() { [native code] }",
65               "[object Set Iterator]", "0", "1", "[object Object]"})
66      public void iterator() throws Exception {
67          final String html = DOCTYPE_HTML
68              + "<html>\n"
69              + "<head>\n"
70              + "<script>\n"
71              + LOG_TITLE_FUNCTION
72              + "  function test() {\n"
73              + "    if (window.Symbol) {\n"
74              + "      var set = new Set();\n"
75              + "      set.add('0');\n"
76              + "      set.add(1);\n"
77              + "      set.add({});\n"
78              + "      log(set[Symbol.iterator]);\n"
79              + "      var iter = set[Symbol.iterator]();\n"
80              + "      log(iter);\n"
81              + "      log(iter.next().value);\n"
82              + "      log(iter.next().value);\n"
83              + "      log(iter.next().value);\n"
84              + "    }\n"
85              + "  }\n"
86              + "</script>\n"
87              + "</head>\n"
88              + "<body onload='test()'>\n"
89              + "</body></html>";
90  
91          loadPageVerifyTitle2(html);
92      }
93  
94      /**
95       * @throws Exception if the test fails
96       */
97      @Test
98      @Alerts({"function values() { [native code] }",
99               "[object Set Iterator]", "0", "1", "[object Object]"})
100     public void values() throws Exception {
101         final String html = DOCTYPE_HTML
102             + "<html>\n"
103             + "<head>\n"
104             + "<script>\n"
105             + LOG_TITLE_FUNCTION
106             + "  function test() {\n"
107             + "    if (window.Symbol) {\n"
108             + "      var set = new Set();\n"
109             + "      set.add('0');\n"
110             + "      set.add(1);\n"
111             + "      set.add({});\n"
112             + "      log(set.values);\n"
113             + "      var iter = set.values();\n"
114             + "      log(iter);\n"
115             + "      log(iter.next().value);\n"
116             + "      log(iter.next().value);\n"
117             + "      log(iter.next().value);\n"
118             + "    }\n"
119             + "  }\n"
120             + "</script>\n"
121             + "</head>\n"
122             + "<body onload='test()'>\n"
123             + "</body></html>";
124 
125         loadPageVerifyTitle2(html);
126     }
127 
128     /**
129      * @throws Exception if the test fails
130      */
131     @Test
132     @Alerts("2")
133     public void constructorArray() throws Exception {
134         final String html = DOCTYPE_HTML
135             + "<html><head>\n"
136             + "<script>\n"
137             + LOG_TITLE_FUNCTION
138             + "function test() {\n"
139             + "  var mySet = new Set([2, 7]);\n"
140             + "  log(mySet.size);\n"
141             + "}\n"
142             + "</script></head><body onload='test()'>\n"
143             + "</body></html>";
144 
145         loadPageVerifyTitle2(html);
146     }
147 
148     /**
149      * @throws Exception if the test fails
150      */
151     @Test
152     @Alerts("2")
153     public void constructorInt32Array() throws Exception {
154         final String html = DOCTYPE_HTML
155             + "<html><head>\n"
156             + "<script>\n"
157             + LOG_TITLE_FUNCTION
158             + "function test() {\n"
159             + "  var array = new Int32Array([2, 7]);\n"
160             + "  var mySet = new Set(array);\n"
161             + "  log(mySet.size);\n"
162             + "}\n"
163             + "</script></head><body onload='test()'>\n"
164             + "</body></html>";
165 
166         loadPageVerifyTitle2(html);
167     }
168 
169     /**
170      * @throws Exception if the test fails
171      */
172     @Test
173     @Alerts({"3", "true", "false"})
174     public void constructorStringParam() throws Exception {
175         final String html = DOCTYPE_HTML
176             + "<html><head>\n"
177             + "<script>\n"
178             + LOG_TITLE_FUNCTION
179             + "function test() {\n"
180             + "  var mySet = new Set('test');\n"
181             + "  log(mySet.size);\n"
182             + "  log(mySet.has('t'));\n"
183             + "  log(mySet.has('x'));\n"
184             + "}\n"
185             + "</script></head><body onload='test()'>\n"
186             + "</body></html>";
187 
188         loadPageVerifyTitle2(html);
189     }
190 
191     /**
192      * @throws Exception if the test fails
193      */
194     @Test
195     @Alerts({"7", "true", "false"})
196     public void constructorStringIteratorParam() throws Exception {
197         final String html = DOCTYPE_HTML
198             + "<html><head>\n"
199             + "<script>\n"
200             + LOG_TITLE_FUNCTION
201             + "function test() {\n"
202             + "  if (window.Symbol) {\n"
203             + "    var strIter = 'HtmlUnit'[Symbol.iterator]();"
204             + "    var mySet = new Set(strIter);\n"
205             + "    log(mySet.size);\n"
206             + "    log(mySet.has('t'));\n"
207             + "    log(mySet.has('x'));\n"
208             + "  }\n"
209             + "}\n"
210             + "</script></head><body onload='test()'>\n"
211             + "</body></html>";
212 
213         loadPageVerifyTitle2(html);
214     }
215 
216     /**
217      * @throws Exception if the test fails
218      */
219     @Test
220     @Alerts({"3", "true", "false"})
221     public void constructorSetParam() throws Exception {
222         final String html = DOCTYPE_HTML
223             + "<html><head>\n"
224             + "<script>\n"
225             + LOG_TITLE_FUNCTION
226             + "function test() {\n"
227             + "  var mySet = new Set(new Set('test'));\n"
228             + "  log(mySet.size);\n"
229             + "  log(mySet.has('t'));\n"
230             + "  log(mySet.has('x'));\n"
231             + "}\n"
232             + "</script></head><body onload='test()'>\n"
233             + "</body></html>";
234 
235         loadPageVerifyTitle2(html);
236     }
237 
238     /**
239      * @throws Exception if the test fails
240      */
241     @Test
242     @Alerts({"2", "false", "false"})
243     public void constructorMapParam() throws Exception {
244         final String html = DOCTYPE_HTML
245             + "<html><head>\n"
246             + "<script>\n"
247             + LOG_TITLE_FUNCTION
248             + "function test() {\n"
249             + "  var kvArray = [['key1', 'value1'], ['key2', 'value2']];\n"
250             + "  var myMap = new Map(kvArray);\n"
251             + "  var mySet = new Set(myMap);\n"
252             + "  log(mySet.size);\n"
253             + "  log(mySet.has('key1'));\n"
254             + "  log(mySet.has('value2'));\n"
255             + "}\n"
256             + "</script></head><body onload='test()'>\n"
257             + "</body></html>";
258 
259         loadPageVerifyTitle2(html);
260     }
261 
262     /**
263      * @throws Exception if the test fails
264      */
265     @Test
266     @Alerts({"1", "#77"})
267     public void constructorIteratorParam() throws Exception {
268         final String html = DOCTYPE_HTML
269             + "<html><head>\n"
270             + "<script>\n"
271             + LOG_TITLE_FUNCTION
272             + "function logElement(value) {\n"
273             + "  log(value);\n"
274             + "}\n"
275             + "function test() {\n"
276             + "  try {\n"
277             + "    var myIterable = {};\n"
278             + "    myIterable[Symbol.iterator] = function() {\n"
279             + "      return {\n"
280             + "        next: function() {\n"
281             + "          if (this._first) {;\n"
282             + "            this._first = false;\n"
283             + "            return { value: '#77', done: false };\n"
284             + "          }\n"
285             + "          return { done: true };\n"
286             + "        },\n"
287             + "        _first: true\n"
288             + "      };\n"
289             + "    };\n"
290             + "    var mySet = new Set(myIterable);\n"
291             + "    log(mySet.size);\n"
292             + "    mySet.forEach(logElement);\n"
293             + "  } catch(e) { logEx(e); }"
294             + "}\n"
295             + "</script></head>\n"
296             + "<body onload='test()'>\n"
297             + "</body></html>";
298 
299         loadPageVerifyTitle2(html);
300     }
301 
302     /**
303      * @throws Exception if the test fails
304      */
305     @Test
306     @Alerts({"ab", "ab", "[object Set]", "[object Window]",
307              "undefined", "undefined", "[object Set]", "[object Window]",
308              "null", "null", "[object Set]", "[object Window]"})
309     public void forEach() throws Exception {
310         final String html = DOCTYPE_HTML
311             + "<html><head>\n"
312             + "<script>\n"
313             + LOG_TITLE_FUNCTION
314             + "function logElement(value1, value2, s) {\n"
315             + "  log(value1);\n"
316             + "  log(value2);\n"
317             + "  log(s);\n"
318             + "  log(this);\n"
319             + "}\n"
320             + "function test() {\n"
321             + "  var mySet = new Set(['ab', undefined, null]);\n"
322             + "  mySet.forEach(logElement);\n"
323             + "}\n"
324             + "</script>\n"
325             + "</head>\n"
326             + "<body onload='test()'>\n"
327             + "</body></html>";
328 
329         loadPageVerifyTitle2(html);
330     }
331 
332     /**
333      * @throws Exception if the test fails
334      */
335     @Test
336     @Alerts({"ab", "ab", "[object Set]", "undefined",
337              "undefined", "undefined", "[object Set]", "undefined",
338              "null", "null", "[object Set]", "undefined"})
339     public void forEachStrict() throws Exception {
340         final String html = DOCTYPE_HTML
341             + "<html><head>\n"
342             + "<script>\n"
343             + "'use strict';\n"
344             + LOG_TITLE_FUNCTION
345             + "function logElement(value1, value2, s) {\n"
346             + "  log(value1);\n"
347             + "  log(value2);\n"
348             + "  log(s);\n"
349             + "  log(this);\n"
350             + "}\n"
351             + "function test() {\n"
352             + "  var mySet = new Set(['ab', undefined, null]);\n"
353             + "  mySet.forEach(logElement);\n"
354             + "}\n"
355             + "</script>\n"
356             + "</head>\n"
357             + "<body onload='test()'>\n"
358             + "</body></html>";
359 
360         loadPageVerifyTitle2(html);
361     }
362 
363     /**
364      * @throws Exception if the test fails
365      */
366     @Test
367     @Alerts({"ab", "ab", "[object Set]", "hello", "undefined", "undefined", "[object Set]", "hello",
368              "null", "null", "[object Set]", "hello"})
369     public void forEachThis() throws Exception {
370         final String html = DOCTYPE_HTML
371             + "<html><head>\n"
372             + "<script>\n"
373             + LOG_TITLE_FUNCTION
374             + "function logElement(value1, value2, s) {\n"
375             + "  log(value1);\n"
376             + "  log(value2);\n"
377             + "  log(s);\n"
378             + "  log(this);\n"
379             + "}\n"
380             + "function test() {\n"
381             + "  var mySet = new Set(['ab', undefined, null]);\n"
382             + "  mySet.forEach(logElement, 'hello');\n"
383             + "}\n"
384             + "</script></head><body onload='test()'>\n"
385             + "</body></html>";
386 
387         loadPageVerifyTitle2(html);
388     }
389 
390     /**
391      * Test case for Bug #1868.
392      *
393      * @throws Exception if the test fails
394      */
395     @Test
396     @Alerts("[object Set Iterator]")
397     public void iteratorPrototype() throws Exception {
398         final String html = DOCTYPE_HTML
399             + "<html>\n"
400             + "<head>\n"
401             + "<script>\n"
402             + LOG_TITLE_FUNCTION
403             + "  function test() {\n"
404             + "    if (window.Symbol) {\n"
405             + "      var mySet = new Set();\n"
406             + "      var iter = mySet[Symbol.iterator]();\n"
407             + "      log(Object.getPrototypeOf(iter));\n"
408             + "    }\n"
409             + "  }\n"
410             + "</script>\n"
411             + "</head>\n"
412             + "<body onload='test()'>\n"
413             + "</body></html>";
414 
415         loadPageVerifyTitle2(html);
416     }
417 
418     /**
419      * Test case for Bug #1886.
420      *
421      * @throws Exception if the test fails
422      */
423     @Test
424     @Alerts({"undefined", "0"})
425     public void forEach_withElision() throws Exception {
426         final String html = DOCTYPE_HTML
427                 + "<html><head>\n"
428                 + "<script>\n"
429                 + LOG_TITLE_FUNCTION
430                 + "function logElement(value) {\n"
431                 + "  log(value);\n"
432                 + "}\n"
433                 + "function test() {\n"
434                 + "  var mySet = new Set([, 0]);\n"
435                 + "  mySet.forEach(logElement);\n"
436                 + "}\n"
437                 + "</script></head><body onload='test()'>\n"
438                 + "</body></html>";
439 
440         loadPageVerifyTitle2(html);
441     }
442 }