JAL-1805 test envirionment separation
[jalview.git] / test / jalview / gui / AnnotationChooserTest.java
1 package jalview.gui;
2
3 import static org.testng.AssertJUnit.assertEquals;
4 import static org.testng.AssertJUnit.assertFalse;
5 import static org.testng.AssertJUnit.assertTrue;
6
7 import jalview.analysis.AnnotationSorter.SequenceAnnotationOrder;
8 import jalview.bin.Cache;
9 import jalview.datamodel.AlignmentAnnotation;
10 import jalview.datamodel.AlignmentI;
11 import jalview.datamodel.Annotation;
12 import jalview.datamodel.SequenceGroup;
13 import jalview.datamodel.SequenceI;
14 import jalview.io.AppletFormatAdapter;
15 import jalview.util.MessageManager;
16
17 import java.awt.BorderLayout;
18 import java.awt.Checkbox;
19 import java.awt.Component;
20 import java.awt.Container;
21 import java.awt.FlowLayout;
22 import java.awt.event.ItemEvent;
23 import java.io.IOException;
24 import java.util.List;
25
26 import javax.swing.JButton;
27 import javax.swing.JPanel;
28
29 import org.testng.annotations.BeforeMethod;
30 import org.testng.annotations.Test;
31
32 /**
33  * Unit tests for AnnotationChooser
34  * 
35  * @author gmcarstairs
36  *
37  */
38 public class AnnotationChooserTest
39 {
40   // 4 sequences x 13 positions
41   final static String TEST_DATA = ">FER_CAPAA Ferredoxin\n"
42           + "TIETHKEAELVG-\n"
43           + ">FER_CAPAN Ferredoxin, chloroplast precursor\n"
44           + "TIETHKEAELVG-\n"
45           + ">FER1_SOLLC Ferredoxin-1, chloroplast precursor\n"
46           + "TIETHKEEELTA-\n" + ">Q93XJ9_SOLTU Ferredoxin I precursor\n"
47           + "TIETHKEEELTA-\n";
48
49   AnnotationChooser testee;
50
51   AlignmentPanel parentPanel;
52
53   AlignFrame af;
54
55   @BeforeMethod
56   public void setUp() throws IOException
57   {
58     // pin down annotation sort order for test
59     Cache.applicationProperties.setProperty(Preferences.SORT_ANNOTATIONS,
60             SequenceAnnotationOrder.NONE.name());
61     final String True = Boolean.TRUE.toString();
62     Cache.applicationProperties.setProperty(
63             Preferences.SHOW_AUTOCALC_ABOVE, True);
64     Cache.applicationProperties.setProperty("SHOW_QUALITY", True);
65     Cache.applicationProperties.setProperty("SHOW_CONSERVATION", True);
66     Cache.applicationProperties.setProperty("SHOW_IDENTITY", True);
67
68     AlignmentI al = new jalview.io.FormatAdapter().readFile(TEST_DATA,
69             AppletFormatAdapter.PASTE, "FASTA");
70     af = new AlignFrame(al, 700, 500);
71     parentPanel = new AlignmentPanel(af, af.getViewport());
72     addAnnotations();
73   }
74
75   /**
76    * Add 4 annotations, 3 of them sequence-specific.
77    * 
78    * <PRE>
79    * ann1 - for sequence 0 - label 'IUPRED' 
80    * ann2 - not sequence related - label 'Beauty' 
81    * ann3 - for sequence 3 - label 'JMol'
82    * ann4 - for sequence 2 - label 'IUPRED'
83    * ann5 - for sequence 1 - label 'JMol'
84    */
85   private void addAnnotations()
86   {
87     Annotation an = new Annotation(2f);
88     Annotation[] anns = new Annotation[]
89     { an, an, an };
90     AlignmentAnnotation ann0 = new AlignmentAnnotation("IUPRED", "", anns);
91     AlignmentAnnotation ann1 = new AlignmentAnnotation("Beauty", "", anns);
92     AlignmentAnnotation ann2 = new AlignmentAnnotation("JMol", "", anns);
93     AlignmentAnnotation ann3 = new AlignmentAnnotation("IUPRED", "", anns);
94     AlignmentAnnotation ann4 = new AlignmentAnnotation("JMol", "", anns);
95     SequenceI[] seqs = parentPanel.getAlignment().getSequencesArray();
96     ann0.setSequenceRef(seqs[0]);
97     ann2.setSequenceRef(seqs[3]);
98     ann3.setSequenceRef(seqs[2]);
99     ann4.setSequenceRef(seqs[1]);
100     parentPanel.getAlignment().addAnnotation(ann0);
101     parentPanel.getAlignment().addAnnotation(ann1);
102     parentPanel.getAlignment().addAnnotation(ann2);
103     parentPanel.getAlignment().addAnnotation(ann3);
104     parentPanel.getAlignment().addAnnotation(ann4);
105   }
106
107   /**
108    * Test creation of panel with OK and Cancel buttons
109    */
110   @Test(groups ={ "Functional" })
111   public void testBuildActionButtonsPanel()
112   {
113     testee = new AnnotationChooser(parentPanel);
114     JPanel jp = testee.buildActionButtonsPanel();
115     assertTrue("Wrong layout", jp.getLayout() instanceof FlowLayout);
116
117     Component[] comps = jp.getComponents();
118     assertEquals("Not 2 action buttons", 2, comps.length);
119
120     final Component jb1 = comps[0];
121     final Component jb2 = comps[1];
122
123     assertEquals("Not 'OK' button", MessageManager.getString("action.ok"),
124             ((JButton) jb1).getText());
125     assertEquals("Wrong button font", JvSwingUtils.getLabelFont(),
126             jb1.getFont());
127
128     assertEquals("Not 'Cancel' button",
129             MessageManager.getString("action.cancel"),
130             ((JButton) jb2).getText());
131     assertEquals("Wrong button font", JvSwingUtils.getLabelFont(),
132             jb2.getFont());
133   }
134
135   /**
136    * Test 'Apply to' has 3 radio buttons enabled, 'Selected Sequences' selected,
137    * when there is a current selection group.
138    */
139   @Test(groups ={ "Functional" })
140   public void testBuildApplyToOptionsPanel_withSelectionGroup()
141   {
142     selectSequences(0, 2, 3);
143     testee = new AnnotationChooser(parentPanel);
144
145     JPanel jp = testee.buildApplyToOptionsPanel();
146     Component[] comps = jp.getComponents();
147     assertEquals("Not 3 radio buttons", 3, comps.length);
148
149     final Checkbox cb1 = (Checkbox) comps[0];
150     final Checkbox cb2 = (Checkbox) comps[1];
151     final Checkbox cb3 = (Checkbox) comps[2];
152
153     assertTrue("Not enabled", cb1.isEnabled());
154     assertTrue("Not enabled", cb2.isEnabled());
155     assertTrue("Not enabled", cb3.isEnabled());
156     assertEquals("Option not selected", cb2, cb2.getCheckboxGroup()
157             .getSelectedCheckbox());
158
159     // check state variables match checkbox selection
160     assertTrue(testee.isApplyToSelectedSequences());
161     assertFalse(testee.isApplyToUnselectedSequences());
162   }
163
164   /**
165    * Add a sequence group to the alignment with the specified sequences (base 0)
166    * in it
167    * 
168    * @param i
169    * @param more
170    */
171   private void selectSequences(int... selected)
172   {
173     SequenceI[] seqs = parentPanel.getAlignment().getSequencesArray();
174     SequenceGroup sg = new SequenceGroup();
175     for (int i : selected)
176     {
177       sg.addSequence(seqs[i], false);
178     }
179     parentPanel.av.setSelectionGroup(sg);
180   }
181
182   /**
183    * Test 'Apply to' has 1 radio button enabled, 'All Sequences' selected, when
184    * there is no current selection group.
185    */
186   @Test(groups ={ "Functional" })
187   public void testBuildApplyToOptionsPanel_noSelectionGroup()
188   {
189     testee = new AnnotationChooser(parentPanel);
190     JPanel jp = testee.buildApplyToOptionsPanel();
191     verifyApplyToOptionsPanel_noSelectionGroup(jp);
192   }
193
194   protected void verifyApplyToOptionsPanel_noSelectionGroup(JPanel jp)
195   {
196     assertTrue("Wrong layout", jp.getLayout() instanceof FlowLayout);
197     Component[] comps = jp.getComponents();
198     assertEquals("Not 3 radio buttons", 3, comps.length);
199
200     final Checkbox cb1 = (Checkbox) comps[0];
201     final Checkbox cb2 = (Checkbox) comps[1];
202     final Checkbox cb3 = (Checkbox) comps[2];
203
204     assertTrue("Not enabled", cb1.isEnabled());
205     assertFalse("Enabled", cb2.isEnabled());
206     assertFalse("Enabled", cb3.isEnabled());
207     assertEquals("Not selected", cb1, cb1.getCheckboxGroup()
208             .getSelectedCheckbox());
209
210     // check state variables match checkbox selection
211     assertTrue(testee.isApplyToSelectedSequences());
212     assertTrue(testee.isApplyToUnselectedSequences());
213
214     assertEquals("Wrong text",
215             MessageManager.getString("label.all_sequences"), cb1.getLabel());
216     assertEquals("Wrong text",
217             MessageManager.getString("label.selected_sequences"),
218             cb2.getLabel());
219     assertEquals("Wrong text",
220             MessageManager.getString("label.except_selected_sequences"),
221             cb3.getLabel());
222   }
223
224   /**
225    * Test Show and Hide radio buttons created, with Hide initially selected.
226    */
227   @Test(groups ={ "Functional" })
228   public void testBuildShowHidePanel()
229   {
230     testee = new AnnotationChooser(parentPanel);
231     JPanel jp = testee.buildShowHidePanel();
232     verifyShowHidePanel(jp);
233
234   }
235
236   protected void verifyShowHidePanel(JPanel jp)
237   {
238     assertTrue("Wrong layout", jp.getLayout() instanceof FlowLayout);
239     Component[] comps = jp.getComponents();
240     assertEquals("Not 2 radio buttons", 2, comps.length);
241
242     final Checkbox cb1 = (Checkbox) comps[0];
243     final Checkbox cb2 = (Checkbox) comps[1];
244
245     assertTrue("Show not enabled", cb1.isEnabled());
246     assertTrue("Hide not enabled", cb2.isEnabled());
247
248     // Hide (button 2) selected; note this may change to none (null)
249     assertEquals("Not selected", cb2, cb2.getCheckboxGroup()
250             .getSelectedCheckbox());
251
252     assertTrue("Show is flagged", !testee.isShowSelected());
253
254     assertEquals("Wrong text",
255             MessageManager.getString("label.show_selected_annotations"),
256             cb1.getLabel());
257     assertEquals("Wrong text",
258             MessageManager.getString("label.hide_selected_annotations"),
259             cb2.getLabel());
260   }
261
262   /**
263    * Test construction of panel containing two sub-panels
264    */
265   @Test(groups ={ "Functional" })
266   public void testBuildShowHideOptionsPanel()
267   {
268     testee = new AnnotationChooser(parentPanel);
269     JPanel jp = testee.buildShowHideOptionsPanel();
270     assertTrue("Wrong layout", jp.getLayout() instanceof BorderLayout);
271     Component[] comps = jp.getComponents();
272     assertEquals("Not 2 sub-panels", 2, comps.length);
273
274     verifyShowHidePanel((JPanel) comps[0]);
275     verifyApplyToOptionsPanel_noSelectionGroup((JPanel) comps[1]);
276   }
277
278   /**
279    * Test that annotation types are (uniquely) identified.
280    * 
281    */
282   @Test(groups ={ "Functional" })
283   public void testGetAnnotationTypes()
284   {
285     selectSequences(1);
286     testee = new AnnotationChooser(parentPanel);
287     // selection group should make no difference to the result
288     // as all annotation types for the alignment are considered
289
290     List<String> types = AnnotationChooser.getAnnotationTypes(
291             parentPanel.getAlignment(), true);
292     assertEquals("Not two annotation types", 2, types.size());
293     assertTrue("IUPRED missing", types.contains("IUPRED"));
294     assertTrue("JMol missing", types.contains("JMol"));
295
296     types = AnnotationChooser.getAnnotationTypes(
297             parentPanel.getAlignment(), false);
298     assertEquals("Not six annotation types", 6, types.size());
299     assertTrue("IUPRED missing", types.contains("IUPRED"));
300     assertTrue("JMol missing", types.contains("JMol"));
301     assertTrue("Beauty missing", types.contains("Beauty"));
302     // These are added by viewmodel.AlignViewport.initAutoAnnotation():
303     assertTrue("Consensus missing", types.contains("Consensus"));
304     assertTrue("Quality missing", types.contains("Quality"));
305     assertTrue("Conservation missing", types.contains("Conservation"));
306   }
307
308   /**
309    * Test result of selecting an annotation type, with 'Hide for all sequences'.
310    * 
311    * We expect all annotations of that type to be set hidden. Other annotations
312    * should be left visible.
313    */
314   @Test(groups ={ "Functional" })
315   public void testSelectType_hideForAll()
316   {
317     selectSequences(1, 2);
318     testee = new AnnotationChooser(parentPanel);
319     final Checkbox hideCheckbox = (Checkbox) getComponent(testee, 1, 0, 1);
320     setSelected(hideCheckbox, true);
321
322     final Checkbox allSequencesCheckbox = (Checkbox) getComponent(testee,
323             1, 1, 0);
324     setSelected(allSequencesCheckbox, true);
325
326     AlignmentAnnotation[] anns = parentPanel.getAlignment()
327             .getAlignmentAnnotation();
328
329     assertTrue(anns[5].visible); // JMol for seq3
330     assertTrue(anns[7].visible); // JMol for seq1
331
332     setSelected(getTypeCheckbox("JMol"), true);
333     assertTrue(anns[0].visible); // Conservation
334     assertTrue(anns[1].visible); // Quality
335     assertTrue(anns[2].visible); // Consensus
336     assertTrue(anns[3].visible); // IUPred for seq0
337     assertTrue(anns[4].visible); // Beauty
338     assertFalse(anns[5].visible); // JMol for seq3 - not selected but hidden
339     assertTrue(anns[6].visible); // IUPRED for seq2
340     assertFalse(anns[7].visible); // JMol for seq1 - selected and hidden
341   }
342
343   /**
344    * Test result of selecting an annotation type, with 'Hide for selected
345    * sequences'.
346    * 
347    * We expect the annotations of that type, linked to the sequence group, to be
348    * set hidden. Other annotations should be left visible.
349    */
350   @Test(groups ={ "Functional" })
351   public void testSelectType_hideForSelected()
352   {
353     selectSequences(1, 2);
354     testee = new AnnotationChooser(parentPanel);
355     final Checkbox hideCheckbox = (Checkbox) getComponent(testee, 1, 0, 1);
356     setSelected(hideCheckbox, true);
357
358     /*
359      * Don't set the 'selected sequences' radio button since this would trigger
360      * an update, including unselected sequences / annotation types
361      */
362     // setSelected(getSelectedSequencesCheckbox());
363
364     AlignmentAnnotation[] anns = parentPanel.getAlignment()
365             .getAlignmentAnnotation();
366
367     assertTrue(anns[7].visible); // JMol for seq1
368
369     setSelected(getTypeCheckbox("JMol"), true);
370     assertTrue(anns[0].visible); // Conservation
371     assertTrue(anns[1].visible); // Quality
372     assertTrue(anns[2].visible); // Consensus
373     assertTrue(anns[3].visible); // IUPred for seq0
374     assertTrue(anns[4].visible); // Beauty
375     assertTrue(anns[5].visible); // JMol for seq3 not in selection group
376     assertTrue(anns[6].visible); // IUPRED for seq2
377     assertFalse(anns[7].visible); // JMol for seq1 in selection group
378   }
379
380   /**
381    * Test result of deselecting an annotation type, with 'Hide for all
382    * sequences'.
383    * 
384    * We expect all annotations of that type to be set visible. Other annotations
385    * should be left unchanged.
386    */
387   @Test(groups ={ "Functional" })
388   public void testDeselectType_hideForAll()
389   {
390     selectSequences(1, 2);
391     testee = new AnnotationChooser(parentPanel);
392
393     final Checkbox hideCheckbox = (Checkbox) getComponent(testee, 1, 0, 1);
394     setSelected(hideCheckbox, true);
395
396     final Checkbox allSequencesCheckbox = (Checkbox) getComponent(testee,
397             1, 1, 0);
398     setSelected(allSequencesCheckbox, true);
399
400     AlignmentAnnotation[] anns = parentPanel.getAlignment()
401             .getAlignmentAnnotation();
402
403     final Checkbox typeCheckbox = getTypeCheckbox("JMol");
404
405     // select JMol - all hidden
406     setSelected(typeCheckbox, true);
407     assertFalse(anns[5].visible); // JMol for seq3
408     assertFalse(anns[7].visible); // JMol for seq1
409
410     // deselect JMol - all unhidden
411     setSelected(typeCheckbox, false);
412     assertTrue(anns[0].visible); // Conservation
413     assertTrue(anns[1].visible); // Quality
414     assertTrue(anns[2].visible); // Consensus
415     assertTrue(anns[3].visible); // IUPred for seq0
416     assertTrue(anns[4].visible); // Beauty
417     assertTrue(anns[5].visible); // JMol for seq3
418     assertTrue(anns[6].visible); // IUPRED for seq2
419     assertTrue(anns[7].visible); // JMol for seq1
420   }
421
422   /**
423    * Test result of deselecting an annotation type, with 'Hide for selected
424    * sequences'.
425    * 
426    * We expect the annotations of that type, linked to the sequence group, to be
427    * set visible. Other annotations should be left unchanged.
428    */
429   @Test(groups ={ "Functional" })
430   public void testDeselectType_hideForSelected()
431   {
432     selectSequences(1, 2);
433     testee = new AnnotationChooser(parentPanel);
434     final Checkbox hideCheckbox = (Checkbox) getComponent(testee, 1, 0, 1);
435     setSelected(hideCheckbox, true);
436
437     /*
438      * Don't set the 'selected sequences' radio button since this would trigger
439      * an update, including unselected sequences / annotation types
440      */
441     // setSelected(getSelectedSequencesCheckbox());
442
443     setSelected(getTypeCheckbox("JMol"), true);
444     setSelected(getTypeCheckbox("JMol"), false);
445
446     AlignmentAnnotation[] anns = parentPanel.getAlignment()
447             .getAlignmentAnnotation();
448     assertTrue(anns[0].visible); // Conservation
449     assertTrue(anns[1].visible); // Quality
450     assertTrue(anns[2].visible); // Consensus
451     assertTrue(anns[3].visible); // IUPred for seq0
452     assertTrue(anns[4].visible); // Beauty
453     assertTrue(anns[5].visible); // JMol for seq3 not in selection group
454     assertTrue(anns[6].visible); // IUPRED for seq2
455     assertTrue(anns[7].visible); // JMol for seq1 in selection group
456   }
457
458   /**
459    * Test result of selecting an annotation type, with 'Show for all sequences'.
460    * 
461    * We expect all annotations of that type to be set visible. Other annotations
462    * should be left unchanged
463    */
464   @Test(groups ={ "Functional" })
465   public void testSelectType_showForAll()
466   {
467     selectSequences(1, 2);
468     testee = new AnnotationChooser(parentPanel);
469     final Checkbox showCheckbox = (Checkbox) getComponent(testee, 1, 0, 0);
470     final Checkbox hideCheckbox = (Checkbox) getComponent(testee, 1, 0, 1);
471
472     final Checkbox allSequencesCheckbox = (Checkbox) getComponent(testee,
473             1, 1, 0);
474
475     AlignmentAnnotation[] anns = parentPanel.getAlignment()
476             .getAlignmentAnnotation();
477
478     // hide all JMol annotations
479     setSelected(allSequencesCheckbox, true);
480     setSelected(hideCheckbox, true);
481     setSelected(getTypeCheckbox("JMol"), true);
482     assertFalse(anns[5].visible); // JMol for seq3
483     assertFalse(anns[7].visible); // JMol for seq1
484     // ...now show them...
485     setSelected(showCheckbox, true);
486     assertTrue(anns[0].visible); // Conservation
487     assertTrue(anns[1].visible); // Quality
488     assertTrue(anns[2].visible); // Consensus
489     assertTrue(anns[3].visible); // IUPred for seq0
490     assertTrue(anns[4].visible); // Beauty
491     assertTrue(anns[5].visible); // JMol for seq3
492     assertTrue(anns[6].visible); // IUPRED for seq2
493     assertTrue(anns[7].visible); // JMol for seq1
494   }
495
496   /**
497    * Test result of selecting an annotation type, with 'Show for selected
498    * sequences'.
499    * 
500    * We expect all annotations of that type, linked to the sequence group, to be
501    * set visible. Other annotations should be left unchanged
502    */
503   @Test(groups ={ "Functional" })
504   public void testSelectType_showForSelected()
505   {
506     // sequences 1 and 2 have annotations IUPred and Jmol
507     selectSequences(1, 2);
508     testee = new AnnotationChooser(parentPanel);
509     final Checkbox showCheckbox = (Checkbox) getComponent(testee, 1, 0, 0);
510     final Checkbox hideCheckbox = (Checkbox) getComponent(testee, 1, 0, 1);
511
512     final Checkbox selectedSequencesCheckbox = (Checkbox) getComponent(
513             testee, 1, 1, 1);
514
515     AlignmentAnnotation[] anns = parentPanel.getAlignment()
516             .getAlignmentAnnotation();
517
518     // hide all JMol annotations in the selection region (== annotation 7)
519     setSelected(selectedSequencesCheckbox, true);
520     setSelected(hideCheckbox, true);
521     setSelected(getTypeCheckbox("JMol"), true);
522
523     assertTrue(anns[5].visible); // JMol for seq3
524     assertFalse(anns[7].visible); // JMol for seq1
525     // ...now show them...
526     setSelected(showCheckbox, true);
527
528     assertTrue(anns[0].visible); // Conservation
529     assertTrue(anns[1].visible); // Quality
530     assertTrue(anns[2].visible); // Consensus
531     assertTrue(anns[3].visible); // IUPred for seq0
532     assertTrue(anns[4].visible); // Beauty
533     assertTrue(anns[5].visible); // JMol for seq3
534     assertTrue(anns[6].visible); // IUPRED for seq2
535     assertTrue(anns[7].visible); // JMol for seq1
536   }
537
538   /**
539    * Test result of deselecting an annotation type, with 'Show for all
540    * sequences'.
541    * 
542    * We expect all annotations of that type to be set hidden. Other annotations
543    * should be left unchanged.
544    */
545   @Test(groups ={ "Functional" })
546   public void testDeselectType_showForAll()
547   {
548     selectSequences(1, 2);
549     testee = new AnnotationChooser(parentPanel);
550
551     final Checkbox showCheckbox = (Checkbox) getComponent(testee, 1, 0, 0);
552     setSelected(showCheckbox, true);
553
554     final Checkbox allSequencesCheckbox = (Checkbox) getComponent(testee,
555             1, 1, 0);
556     setSelected(allSequencesCheckbox, true);
557
558     AlignmentAnnotation[] anns = parentPanel.getAlignment()
559             .getAlignmentAnnotation();
560
561     final Checkbox typeCheckbox = getTypeCheckbox("JMol");
562     // select JMol - all shown
563     setSelected(typeCheckbox, true);
564     assertTrue(anns[5].visible); // JMol for seq3
565     assertTrue(anns[7].visible); // JMol for seq1
566
567     // deselect JMol - all hidden
568     setSelected(typeCheckbox, false);
569     assertTrue(anns[0].visible); // Conservation
570     assertTrue(anns[1].visible); // Quality
571     assertTrue(anns[2].visible); // Consensus
572     assertTrue(anns[3].visible); // IUPred for seq0
573     assertTrue(anns[4].visible); // Beauty
574     assertFalse(anns[5].visible); // JMol for seq3
575     assertTrue(anns[6].visible); // IUPRED for seq2
576     assertFalse(anns[7].visible); // JMol for seq1
577   }
578
579   /**
580    * Test result of deselecting an annotation type, with 'Show for selected
581    * sequences'.
582    * 
583    * We expect the annotations of that type, linked to the sequence group, to be
584    * set hidden. Other annotations should be left unchanged.
585    */
586   @Test(groups ={ "Functional" })
587   public void testDeselectType_showForSelected()
588   {
589     selectSequences(1, 2);
590     testee = new AnnotationChooser(parentPanel);
591     final Checkbox showCheckbox = (Checkbox) getComponent(testee, 1, 0, 0);
592     setSelected(showCheckbox, true);
593
594     /*
595      * Don't set the 'selected sequences' radio button since this would trigger
596      * an update, including unselected sequences / annotation types
597      */
598     // setSelected(getSelectedSequencesCheckbox());
599
600     AlignmentAnnotation[] anns = parentPanel.getAlignment()
601             .getAlignmentAnnotation();
602
603     // select JMol - should remain visible
604     setSelected(getTypeCheckbox("JMol"), true);
605     assertTrue(anns[5].visible); // JMol for seq3
606     assertTrue(anns[7].visible); // JMol for seq1
607
608     // deselect JMol - should be hidden for selected sequences only
609     setSelected(getTypeCheckbox("JMol"), false);
610     assertTrue(anns[0].visible); // Conservation
611     assertTrue(anns[1].visible); // Quality
612     assertTrue(anns[2].visible); // Consensus
613     assertTrue(anns[3].visible); // IUPred for seq0
614     assertTrue(anns[4].visible); // Beauty
615     assertTrue(anns[5].visible); // JMol for seq3 not in selection group
616     assertTrue(anns[6].visible); // IUPRED for seq2
617     assertFalse(anns[7].visible); // JMol for seq1 in selection group
618   }
619
620   /**
621    * Helper method to drill down to a sub-component in a Container hierarchy.
622    * 
623    * @param cont
624    * @param i
625    * @param j
626    * @param k
627    * @return
628    */
629   public static Component getComponent(Container cont, int... positions)
630   {
631     Component comp = cont;
632     for (int i : positions)
633     {
634       comp = ((Container) comp).getComponent(i);
635     }
636     return comp;
637   }
638
639   /**
640    * Helper method to set or unset a checkbox and fire its action listener.
641    * 
642    * @param cb
643    * @param select
644    */
645   protected void setSelected(Checkbox cb, boolean select)
646   {
647     // TODO refactor to a test utility class
648     cb.setState(select);
649     // have to manually fire the action listener
650     cb.getItemListeners()[0].itemStateChanged(new ItemEvent(cb,
651             ItemEvent.ITEM_STATE_CHANGED, cb, select ? ItemEvent.SELECTED
652                     : ItemEvent.DESELECTED));
653   }
654
655   /**
656    * Helper method to drill down to the 'Annotation type' checkbox with given
657    * label.
658    * 
659    * @return
660    */
661   private Checkbox getTypeCheckbox(String forLabel)
662   {
663     Component[] cbs = ((JPanel) testee.getComponent(0)).getComponents();
664     for (Component comp : cbs)
665     {
666       final Checkbox cb = (Checkbox) comp;
667       if (cb.getLabel().equals(forLabel))
668       {
669         return cb;
670       }
671     }
672     return null;
673   }
674
675   /**
676    * Test isInActionScope for the case where the scope is selected sequences.
677    * Test cases include sequences in the selection group, and others not in the
678    * group.
679    */
680   @Test(groups ={ "Functional" })
681   public void testIsInActionScope_selectedScope()
682   {
683     // sequences 1 and 2 have annotations 4 and 3 respectively
684     selectSequences(1, 2);
685     testee = new AnnotationChooser(parentPanel);
686
687     final Checkbox selectedSequencesCheckbox = (Checkbox) getComponent(
688             testee, 1, 1, 1);
689     setSelected(selectedSequencesCheckbox, true);
690
691     AlignmentAnnotation[] anns = parentPanel.getAlignment()
692             .getAlignmentAnnotation();
693     // remember 3 annotations to skip (Conservation/Quality/Consensus)
694     assertFalse(testee.isInActionScope(anns[3]));
695     assertFalse(testee.isInActionScope(anns[4]));
696     assertFalse(testee.isInActionScope(anns[5]));
697     assertTrue(testee.isInActionScope(anns[6]));
698     assertTrue(testee.isInActionScope(anns[7]));
699   }
700
701   /**
702    * Test isInActionScope for the case where the scope is unselected sequences.
703    * Test cases include sequences in the selection group, and others not in the
704    * group.
705    */
706   @Test(groups ={ "Functional" })
707   public void testIsInActionScope_unselectedScope()
708   {
709     // sequences 1 and 2 have annotations 4 and 3 respectively
710     selectSequences(1, 2);
711     testee = new AnnotationChooser(parentPanel);
712
713     final Checkbox unselectedSequencesCheckbox = (Checkbox) getComponent(
714             testee, 1, 1, 2);
715     setSelected(unselectedSequencesCheckbox, true);
716
717     AlignmentAnnotation[] anns = parentPanel.getAlignment()
718             .getAlignmentAnnotation();
719     // remember 3 annotations to skip (Conservation/Quality/Consensus)
720     assertTrue(testee.isInActionScope(anns[3]));
721     assertTrue(testee.isInActionScope(anns[4]));
722     assertTrue(testee.isInActionScope(anns[5]));
723     assertFalse(testee.isInActionScope(anns[6]));
724     assertFalse(testee.isInActionScope(anns[7]));
725   }
726
727   /**
728    * Test that the reset method restores previous visibility flags.
729    */
730   @Test(groups ={ "Functional" })
731   public void testResetOriginalState()
732   {
733     testee = new AnnotationChooser(parentPanel);
734
735     AlignmentAnnotation[] anns = parentPanel.getAlignment()
736             .getAlignmentAnnotation();
737     // all start visible
738     for (int i = 0; i < anns.length; i++)
739     {
740       assertTrue(i + "'th sequence not visible", anns[i].visible);
741     }
742
743     final Checkbox hideCheckbox = (Checkbox) getComponent(testee, 1, 0, 1);
744     setSelected(hideCheckbox, true);
745
746     final Checkbox allSequencesCheckbox = (Checkbox) getComponent(testee,
747             1, 1, 0);
748     setSelected(allSequencesCheckbox, true);
749
750     setSelected(getTypeCheckbox("JMol"), true);
751     setSelected(getTypeCheckbox("IUPRED"), true);
752
753     assertTrue(anns[0].visible); // Conservation
754     assertTrue(anns[1].visible); // Quality
755     assertTrue(anns[2].visible); // Consensus
756     assertTrue(anns[3].visible); // Beauty (not seq-related)
757     assertFalse(anns[4].visible); // IUPRED
758     assertFalse(anns[5].visible); // JMol
759     assertFalse(anns[6].visible); // IUPRED
760     assertFalse(anns[7].visible); // JMol
761
762     // reset - should all be visible
763     testee.resetOriginalState();
764     for (int i = 0; i < anns.length; i++)
765     {
766       assertTrue(i + "'th sequence not visible", anns[i].visible);
767     }
768   }
769 }