1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package jakarta.faces.component;
20
21 import static org.easymock.EasyMock.aryEq;
22 import static org.easymock.EasyMock.eq;
23 import static org.easymock.EasyMock.expect;
24 import static org.junit.Assert.assertEquals;
25 import static org.junit.Assert.assertNull;
26 import static org.junit.Assert.fail;
27
28 import java.lang.reflect.Method;
29 import java.util.Collection;
30 import java.util.HashMap;
31 import java.util.HashSet;
32 import java.util.Iterator;
33 import java.util.Locale;
34 import java.util.Map;
35
36 import jakarta.el.ELContext;
37 import jakarta.el.MethodExpression;
38 import jakarta.faces.FactoryFinder;
39 import jakarta.faces.application.Application;
40 import jakarta.faces.application.ProjectStage;
41 import jakarta.faces.application.ViewHandler;
42 import jakarta.faces.context.ExternalContext;
43 import jakarta.faces.event.AbortProcessingException;
44 import jakarta.faces.event.ActionEvent;
45 import jakarta.faces.event.ActionListener;
46 import jakarta.faces.event.PhaseEvent;
47 import jakarta.faces.event.PhaseId;
48 import jakarta.faces.event.PhaseListener;
49 import jakarta.faces.lifecycle.Lifecycle;
50 import jakarta.faces.lifecycle.LifecycleFactory;
51 import jakarta.faces.webapp.FacesServlet;
52
53 import org.apache.myfaces.TestRunner;
54 import org.apache.myfaces.test.base.junit4.AbstractJsfTestCase;
55 import org.apache.myfaces.test.mock.MockFacesContext;
56 import org.easymock.classextension.EasyMock;
57 import org.easymock.classextension.IMocksControl;
58 import org.junit.After;
59 import org.junit.Before;
60 import org.junit.Test;
61
62 public class UIViewRootTest extends AbstractJsfTestCase
63 {
64 private Map<PhaseId, Class<? extends PhaseListener>> phaseListenerClasses;
65 private IMocksControl _mocksControl;
66 private MockFacesContext _facesContext;
67 private UIViewRoot _testimpl;
68 private ExternalContext _externalContext;
69 private Application _application;
70 private Lifecycle _lifecycle;
71 private LifecycleFactory _lifecycleFactory;
72 private ViewHandler _viewHandler;
73 private ELContext _elContext;
74
75 private static ThreadLocal<LifecycleFactory> LIFECYCLEFACTORY = new ThreadLocal<LifecycleFactory>();
76
77 @Before
78 public void setUp() throws Exception
79 {
80 super.setUp();
81 phaseListenerClasses = new HashMap<PhaseId, Class<? extends PhaseListener>>();
82 phaseListenerClasses.put(PhaseId.APPLY_REQUEST_VALUES, ApplyRequesValuesPhaseListener.class);
83 phaseListenerClasses.put(PhaseId.PROCESS_VALIDATIONS, ProcessValidationsPhaseListener.class);
84 phaseListenerClasses.put(PhaseId.UPDATE_MODEL_VALUES, UpdateModelValuesPhaseListener.class);
85 phaseListenerClasses.put(PhaseId.INVOKE_APPLICATION, InvokeApplicationPhaseListener.class);
86 phaseListenerClasses.put(PhaseId.RENDER_RESPONSE, RenderResponsePhaseListener.class);
87
88 _mocksControl = EasyMock.createControl();
89 _externalContext = _mocksControl.createMock(ExternalContext.class);
90 _facesContext = (MockFacesContext) facesContext;
91 _application = _mocksControl.createMock(Application.class);
92 _lifecycleFactory = _mocksControl.createMock(LifecycleFactory.class);
93 _testimpl = new UIViewRoot();
94 _lifecycle = _mocksControl.createMock(Lifecycle.class);
95 _elContext = _mocksControl.createMock(ELContext.class);
96 _viewHandler = _mocksControl.createMock(ViewHandler.class);
97 _facesContext.setELContext(_elContext);
98
99 LIFECYCLEFACTORY.set(_lifecycleFactory);
100 FactoryFinder.setFactory(FactoryFinder.LIFECYCLE_FACTORY, MockLifeCycleFactory.class.getName());
101 servletContext.addInitParameter(ProjectStage.PROJECT_STAGE_PARAM_NAME, ProjectStage.UnitTest.name());
102
103 }
104
105 @After
106 public void tearDown() throws Exception
107 {
108 super.tearDown();
109 _mocksControl.reset();
110 }
111
112 @Test
113 public void testSuperClass() throws Exception
114 {
115 assertEquals(UIComponentBase.class, UIViewRoot.class.getSuperclass());
116 }
117
118 @Test
119 public void testComponentType() throws Exception
120 {
121 assertEquals("jakarta.faces.ViewRoot", UIViewRoot.COMPONENT_TYPE);
122 }
123
124 @Test
125 public void testLocale() throws Exception
126 {
127 expect(_application.getViewHandler()).andReturn(_viewHandler).anyTimes();
128 expect(_viewHandler.calculateLocale(_facesContext)).andReturn(null).anyTimes();
129 _mocksControl.replay();
130
131 _facesContext.setApplication(_application);
132 assertNull(_testimpl.getLocale());
133 _testimpl.setLocale(Locale.JAPANESE);
134 assertEquals(Locale.JAPANESE, _testimpl.getLocale());
135 _mocksControl.verify();
136 }
137
138
139
140
141 @Test
142 public void testCreateUniqueId()
143 {
144
145
146
147
148
149
150
151
152 _mocksControl.replay();
153 Collection<String> createdIds = new HashSet<String>();
154 for (int i = 0; i < 10000; i++)
155 {
156 if (!createdIds.add(_testimpl.createUniqueId()))
157 {
158 fail("duplicate id created");
159 }
160 }
161 _mocksControl.verify();
162 }
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432 private void testProcessXXX(TestRunner runner, PhaseId phaseId, boolean expectSuperCall, boolean checkBefore,
433 boolean checkAfter) throws Throwable
434 {
435 expect(_lifecycleFactory.getLifecycle(eq(LifecycleFactory.DEFAULT_LIFECYCLE))).andReturn(_lifecycle);
436 expect(_externalContext.getInitParameter(eq(FacesServlet.LIFECYCLE_ID_ATTR))).andReturn(null).anyTimes();
437
438 PhaseEvent event = new PhaseEvent(_facesContext, phaseId, _lifecycle);
439
440 if (expectSuperCall)
441 {
442 _testimpl = _mocksControl.createMock(UIViewRoot.class, new Method[]{UIViewRoot.class.getMethod(
443 "isRendered", new Class[0])});
444 }
445
446 MethodExpression beforeListener = _mocksControl.createMock(MethodExpression.class);
447 _testimpl.setBeforePhaseListener(beforeListener);
448
449 MethodExpression afterListener = _mocksControl.createMock(MethodExpression.class);
450 _testimpl.setAfterPhaseListener(afterListener);
451
452 Method[] mockedMethods = new Method[] {
453 PhaseListener.class.getMethod("beforePhase", new Class[] { PhaseEvent.class }),
454 PhaseListener.class.getMethod("afterPhase", new Class[] { PhaseEvent.class }) };
455 PhaseListener phaseListener = _mocksControl.createMock(phaseListenerClasses.get(phaseId), mockedMethods);
456 _testimpl.addPhaseListener(phaseListener);
457
458 PhaseListener anyPhaseListener = _mocksControl.createMock(AnyPhasePhaseListener.class, mockedMethods);
459 _testimpl.addPhaseListener(anyPhaseListener);
460
461 PhaseListener restoreViewPhaseListener = _mocksControl.createMock(RestoreViewPhasePhaseListener.class,
462 mockedMethods);
463 _testimpl.addPhaseListener(restoreViewPhaseListener);
464
465 _mocksControl.checkOrder(true);
466
467 if (checkBefore)
468 {
469 expect(beforeListener.invoke(eq(_facesContext.getELContext()), aryEq(new Object[] { event }))).andReturn(
470 null);
471 phaseListener.beforePhase(eq(event));
472 anyPhaseListener.beforePhase(eq(event));
473 }
474
475 if (expectSuperCall)
476 {
477 expect(_testimpl.isRendered()).andReturn(false);
478 }
479
480 if (checkAfter)
481 {
482 expect(afterListener.invoke(eq(_facesContext.getELContext()), aryEq(new Object[] { event }))).andReturn(
483 null);
484 phaseListener.afterPhase(eq(event));
485 anyPhaseListener.afterPhase(eq(event));
486 }
487
488 _mocksControl.replay();
489 runner.run();
490 _mocksControl.verify();
491 }
492
493 private final class ActionListenerImplementation implements ActionListener
494 {
495 public int invocationCount = 0;
496
497 public ActionEvent newActionEventFromListener;
498
499 public ActionListenerImplementation(UICommand otherUiCommand)
500 {
501
502
503 newActionEventFromListener = new ActionEvent(otherUiCommand);
504 }
505
506 public void processAction(ActionEvent actionEvent)
507 throws AbortProcessingException
508 {
509 invocationCount++;
510
511 newActionEventFromListener.queue();
512
513
514 actionEvent.queue();
515 }
516 }
517
518 public static class MockLifeCycleFactory extends LifecycleFactory
519 {
520
521 @Override
522 public void addLifecycle(String lifecycleId, Lifecycle lifecycle)
523 {
524 LIFECYCLEFACTORY.get().addLifecycle(lifecycleId, lifecycle);
525 }
526
527 @Override
528 public Lifecycle getLifecycle(String lifecycleId)
529 {
530 return LIFECYCLEFACTORY.get().getLifecycle(lifecycleId);
531 }
532
533 @Override
534 public Iterator<String> getLifecycleIds()
535 {
536 return LIFECYCLEFACTORY.get().getLifecycleIds();
537 }
538
539 }
540
541 public static abstract class ApplyRequesValuesPhaseListener implements PhaseListener
542 {
543 public PhaseId getPhaseId()
544 {
545 return PhaseId.APPLY_REQUEST_VALUES;
546 }
547 }
548
549 public static abstract class ProcessValidationsPhaseListener implements PhaseListener
550 {
551 public PhaseId getPhaseId()
552 {
553 return PhaseId.PROCESS_VALIDATIONS;
554 }
555 }
556
557 public static abstract class UpdateModelValuesPhaseListener implements PhaseListener
558 {
559 public PhaseId getPhaseId()
560 {
561 return PhaseId.UPDATE_MODEL_VALUES;
562 }
563 }
564
565 public static abstract class InvokeApplicationPhaseListener implements PhaseListener
566 {
567 public PhaseId getPhaseId()
568 {
569 return PhaseId.INVOKE_APPLICATION;
570 }
571 }
572
573 public static abstract class AnyPhasePhaseListener implements PhaseListener
574 {
575 public PhaseId getPhaseId()
576 {
577 return PhaseId.ANY_PHASE;
578 }
579 }
580
581 public static abstract class RestoreViewPhasePhaseListener implements PhaseListener
582 {
583 public PhaseId getPhaseId()
584 {
585 return PhaseId.RESTORE_VIEW;
586 }
587 }
588
589 public static abstract class RenderResponsePhaseListener implements PhaseListener
590 {
591 public PhaseId getPhaseId()
592 {
593 return PhaseId.RENDER_RESPONSE;
594 }
595 }
596
597 @Test
598 public void testBroadcastEvents()
599 {
600
601 UICommand uiCommand = new UICommand();
602 uiCommand.setId("idOfCommandOne");
603 facesContext.getViewRoot().getChildren().add(uiCommand);
604
605
606
607
608 UICommand differentUiCommand = new UICommand();
609 uiCommand.setId("idOfdifferentUiCommand");
610 facesContext.getViewRoot().getChildren().add(differentUiCommand);
611
612
613 ActionListenerImplementation actionListener = new ActionListenerImplementation(differentUiCommand);
614 uiCommand.addActionListener(actionListener);
615
616 ActionListener differentActionListener = org.easymock.EasyMock.createNiceMock(ActionListener.class);
617 differentActionListener.processAction(actionListener.newActionEventFromListener);
618 org.easymock.EasyMock.expectLastCall().times(1);
619 org.easymock.EasyMock.replay(differentActionListener);
620 differentUiCommand.addActionListener(differentActionListener);
621
622
623 ActionEvent invokeApplicationEvent = new ActionEvent(uiCommand);
624 invokeApplicationEvent.queue();
625
626
627
628 facesContext.getViewRoot().broadcastEvents(facesContext, PhaseId.INVOKE_APPLICATION);
629
630 assertEquals(15, actionListener.invocationCount);
631 org.easymock.EasyMock.verify(differentActionListener);
632 }
633
634 }