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