JAL-3225 updated essential files for eclipse project if buildship fails
[jalview.git] / test / jalview / gui / PopupMenuTest.java
1 /*
2  * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3  * Copyright (C) $$Year-Rel$$ The Jalview Authors
4  * 
5  * This file is part of Jalview.
6  * 
7  * Jalview is free software: you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License 
9  * as published by the Free Software Foundation, either version 3
10  * of the License, or (at your option) any later version.
11  *  
12  * Jalview is distributed in the hope that it will be useful, but 
13  * WITHOUT ANY WARRANTY; without even the implied warranty 
14  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
15  * PURPOSE.  See the GNU General Public License for more details.
16  * 
17  * You should have received a copy of the GNU General Public License
18  * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
19  * The Jalview Authors are detailed in the 'AUTHORS' file.
20  */
21 package jalview.gui;
22
23 import static jalview.util.UrlConstants.DB_ACCESSION;
24 import static jalview.util.UrlConstants.SEQUENCE_ID;
25 import static org.testng.AssertJUnit.assertEquals;
26 import static org.testng.AssertJUnit.assertFalse;
27 import static org.testng.AssertJUnit.assertTrue;
28
29 import jalview.bin.Cache;
30 import jalview.datamodel.AlignmentAnnotation;
31 import jalview.datamodel.AlignmentI;
32 import jalview.datamodel.Annotation;
33 import jalview.datamodel.ColumnSelection;
34 import jalview.datamodel.DBRefEntry;
35 import jalview.datamodel.DBRefSource;
36 import jalview.datamodel.HiddenColumns;
37 import jalview.datamodel.Sequence;
38 import jalview.datamodel.SequenceFeature;
39 import jalview.datamodel.SequenceGroup;
40 import jalview.datamodel.SequenceI;
41 import jalview.io.DataSourceType;
42 import jalview.io.FileFormat;
43 import jalview.io.FormatAdapter;
44 import jalview.urls.api.UrlProviderFactoryI;
45 import jalview.urls.desktop.DesktopUrlProviderFactory;
46 import jalview.util.MessageManager;
47 import jalview.util.UrlConstants;
48
49 import java.awt.Component;
50 import java.io.IOException;
51 import java.util.ArrayList;
52 import java.util.Collections;
53 import java.util.Iterator;
54 import java.util.List;
55
56 import javax.swing.JMenu;
57 import javax.swing.JMenuItem;
58 import javax.swing.JPopupMenu;
59 import javax.swing.JSeparator;
60
61 import org.testng.annotations.BeforeClass;
62 import org.testng.annotations.BeforeMethod;
63 import org.testng.annotations.Test;
64
65 public class PopupMenuTest
66 {
67
68   @BeforeClass(alwaysRun = true)
69   public void setUpJvOptionPane()
70   {
71     JvOptionPane.setInteractiveMode(false);
72     JvOptionPane.setMockResponse(JvOptionPane.CANCEL_OPTION);
73   }
74
75   // 4 sequences x 13 positions
76   final static String TEST_DATA = ">FER_CAPAA Ferredoxin\n"
77           + "TIETHKEAELVG-\n"
78           + ">FER_CAPAN Ferredoxin, chloroplast precursor\n"
79           + "TIETHKEAELVG-\n"
80           + ">FER1_SOLLC Ferredoxin-1, chloroplast precursor\n"
81           + "TIETHKEEELTA-\n" + ">Q93XJ9_SOLTU Ferredoxin I precursor\n"
82           + "TIETHKEEELTA-\n";
83
84   AlignmentI alignment;
85
86   AlignmentPanel parentPanel;
87
88   PopupMenu testee = null;
89
90   @BeforeMethod(alwaysRun = true)
91   public void setUp() throws IOException
92   {
93     Cache.loadProperties("test/jalview/io/testProps.jvprops");
94     Cache.initLogger();
95
96     String inMenuString = ("EMBL-EBI Search | http://www.ebi.ac.uk/ebisearch/search.ebi?db=allebi&query=$"
97             + SEQUENCE_ID
98             + "$"
99             + "|"
100             + "UNIPROT | http://www.uniprot.org/uniprot/$" + DB_ACCESSION + "$")
101             + "|"
102             + ("INTERPRO | http://www.ebi.ac.uk/interpro/entry/$"
103                     + DB_ACCESSION + "$")
104             + "|"
105             +
106             // Gene3D entry tests for case (in)sensitivity
107             ("Gene3D | http://gene3d.biochem.ucl.ac.uk/Gene3D/search?sterm=$"
108                     + DB_ACCESSION + "$&mode=protein");
109
110     UrlProviderFactoryI factory = new DesktopUrlProviderFactory(
111             UrlConstants.DEFAULT_LABEL, inMenuString, "");
112     Preferences.sequenceUrlLinks = factory.createUrlProvider();
113
114     alignment = new FormatAdapter().readFile(TEST_DATA,
115             DataSourceType.PASTE, FileFormat.Fasta);
116     AlignFrame af = new AlignFrame(alignment, 700, 500);
117     parentPanel = new AlignmentPanel(af, af.getViewport());
118     testee = new PopupMenu(parentPanel, alignment.getSequenceAt(0), null);
119     int i = 0;
120     for (SequenceI seq : alignment.getSequences())
121     {
122       final AlignmentAnnotation annotation = new AlignmentAnnotation(
123               "label" + i, "desc" + i, i);
124       annotation.setCalcId("calcId" + i);
125       seq.addAlignmentAnnotation(annotation);
126       annotation.setSequenceRef(seq);
127     }
128   }
129
130   @Test(groups = { "Functional" })
131   public void testConfigureReferenceAnnotationsMenu_noSequenceSelected()
132   {
133     JMenuItem menu = new JMenuItem();
134     List<SequenceI> seqs = new ArrayList<>();
135     testee.configureReferenceAnnotationsMenu(menu, seqs);
136     assertFalse(menu.isEnabled());
137     // now try null list
138     menu.setEnabled(true);
139     testee.configureReferenceAnnotationsMenu(menu, null);
140     assertFalse(menu.isEnabled());
141   }
142
143   /**
144    * Test building the 'add reference annotations' menu for the case where there
145    * are no reference annotations to add to the alignment. The menu item should
146    * be disabled.
147    */
148   @Test(groups = { "Functional" })
149   public void testConfigureReferenceAnnotationsMenu_noReferenceAnnotations()
150   {
151     JMenuItem menu = new JMenuItem();
152
153     /*
154      * Initial state is that sequences have annotations, and have dataset
155      * sequences, but the dataset sequences have no annotations. Hence nothing
156      * to add.
157      */
158     List<SequenceI> seqs = parentPanel.getAlignment().getSequences();
159
160     testee.configureReferenceAnnotationsMenu(menu, seqs);
161     assertFalse(menu.isEnabled());
162   }
163
164   /**
165    * Test building the 'add reference annotations' menu for the case where all
166    * reference annotations are already on the alignment. The menu item should be
167    * disabled.
168    */
169   @Test(groups = { "Functional" })
170   public void testConfigureReferenceAnnotationsMenu_alreadyAdded()
171   {
172     JMenuItem menu = new JMenuItem();
173     List<SequenceI> seqs = parentPanel.getAlignment().getSequences();
174
175     // make up new annotations and add to dataset sequences, sequences and
176     // alignment
177     attachReferenceAnnotations(seqs, true, true);
178
179     testee.configureReferenceAnnotationsMenu(menu, seqs);
180     assertFalse(menu.isEnabled());
181   }
182
183   /**
184    * Test building the 'add reference annotations' menu for the case where
185    * several reference annotations are on the dataset but not on the sequences.
186    * The menu item should be enabled, and acquire a tooltip which lists the
187    * annotation sources (calcIds) and type (labels).
188    */
189   @Test(groups = { "Functional" })
190   public void testConfigureReferenceAnnotationsMenu()
191   {
192     JMenuItem menu = new JMenuItem();
193     List<SequenceI> seqs = parentPanel.getAlignment().getSequences();
194
195     // make up new annotations and add to dataset sequences
196     attachReferenceAnnotations(seqs, false, false);
197
198     testee.configureReferenceAnnotationsMenu(menu, seqs);
199     assertTrue(menu.isEnabled());
200     String s = MessageManager.getString("label.add_annotations_for");
201     // String expected = "<html><style> p.ttip {width: 350; text-align: justify;
202     // word-wrap: break-word;}</style><p class=\"ttip\">"
203     // + s + "<br/>Jmol/secondary structure<br/>PDB/Temp</p></html>";
204     String expected = "<html><style> div.ttip {width:350px;white-space:pre-wrap;padding:2px;overflow-wrap:break-word;}</style>"
205             + "<div class=\"ttip\">" + s
206             + "<br/>Jmol/secondary structure<br/>PDB/Temp </div></html>";
207     assertEquals(expected, menu.getToolTipText());
208   }
209
210   /**
211    * Test building the 'add reference annotations' menu for the case where
212    * several reference annotations are on the dataset and the sequences but not
213    * on the alignment. The menu item should be enabled, and acquire a tooltip
214    * which lists the annotation sources (calcIds) and type (labels).
215    */
216   @Test(groups = { "Functional" })
217   public void testConfigureReferenceAnnotationsMenu_notOnAlignment()
218   {
219     JMenuItem menu = new JMenuItem();
220     List<SequenceI> seqs = parentPanel.getAlignment().getSequences();
221
222     // make up new annotations and add to dataset sequences and sequences
223     attachReferenceAnnotations(seqs, true, false);
224
225     testee.configureReferenceAnnotationsMenu(menu, seqs);
226     assertTrue(menu.isEnabled());
227     String s = MessageManager.getString("label.add_annotations_for");
228     // String expected = "<html><style> p.ttip {width: 350; text-align: justify;
229     // word-wrap: break-word;}</style><p class=\"ttip\">"
230     // + s + "<br/>Jmol/secondary structure<br/>PDB/Temp</p></html>";
231     String expected = "<html><style> div.ttip {width:350px;white-space:pre-wrap;padding:2px;overflow-wrap:break-word;}</style>"
232             + "<div class=\"ttip\">Add annotations for<br/>Jmol/secondary structure<br/>PDB/Temp </div></html>";
233     assertEquals(expected, menu.getToolTipText());
234   }
235
236   /**
237    * Generate annotations and add to dataset sequences and (optionally)
238    * sequences and/or alignment
239    * 
240    * @param seqs
241    * @param addToSequence
242    * @param addToAlignment
243    */
244   private void attachReferenceAnnotations(List<SequenceI> seqs,
245           boolean addToSequence, boolean addToAlignment)
246   {
247     // PDB.secondary structure on Sequence0
248     AlignmentAnnotation annotation = new AlignmentAnnotation(
249             "secondary structure", "", 0);
250     annotation.setCalcId("PDB");
251     seqs.get(0).getDatasetSequence().addAlignmentAnnotation(annotation);
252     if (addToSequence)
253     {
254       seqs.get(0).addAlignmentAnnotation(annotation);
255     }
256     if (addToAlignment)
257     {
258       this.alignment.addAnnotation(annotation);
259     }
260
261     // PDB.Temp on Sequence1
262     annotation = new AlignmentAnnotation("Temp", "", 0);
263     annotation.setCalcId("PDB");
264     seqs.get(1).getDatasetSequence().addAlignmentAnnotation(annotation);
265     if (addToSequence)
266     {
267       seqs.get(1).addAlignmentAnnotation(annotation);
268     }
269     if (addToAlignment)
270     {
271       this.alignment.addAnnotation(annotation);
272     }
273
274     // JMOL.secondary structure on Sequence0
275     annotation = new AlignmentAnnotation("secondary structure", "", 0);
276     annotation.setCalcId("Jmol");
277     seqs.get(0).getDatasetSequence().addAlignmentAnnotation(annotation);
278     if (addToSequence)
279     {
280       seqs.get(0).addAlignmentAnnotation(annotation);
281     }
282     if (addToAlignment)
283     {
284       this.alignment.addAnnotation(annotation);
285     }
286   }
287
288   /**
289    * Test building the 'add reference annotations' menu for the case where there
290    * are two alignment views:
291    * <ul>
292    * <li>in one view, reference annotations have been added (are on the
293    * datasets, sequences and alignment)</li>
294    * <li>in the current view, reference annotations are on the dataset and
295    * sequence, but not the alignment</li>
296    * </ul>
297    * The menu item should be enabled, and acquire a tooltip which lists the
298    * annotation sources (calcIds) and type (labels).
299    */
300   @Test(groups = { "Functional" })
301   public void testConfigureReferenceAnnotationsMenu_twoViews()
302   {
303   }
304
305   /**
306    * Test for building menu options including 'show' and 'hide' annotation
307    * types.
308    */
309   @Test(groups = { "Functional" })
310   public void testBuildAnnotationTypesMenus()
311   {
312     JMenu showMenu = new JMenu();
313     JMenu hideMenu = new JMenu();
314     List<SequenceI> seqs = parentPanel.getAlignment().getSequences();
315
316     // make up new annotations and add to sequences and to the alignment
317
318     // PDB.secondary structure on Sequence0
319     AlignmentAnnotation annotation = new AlignmentAnnotation(
320             "secondary structure", "", new Annotation[] {});
321     annotation.setCalcId("PDB");
322     annotation.visible = true;
323     seqs.get(0).addAlignmentAnnotation(annotation);
324     parentPanel.getAlignment().addAnnotation(annotation);
325
326     // JMOL.secondary structure on Sequence0 - hidden
327     annotation = new AlignmentAnnotation("secondary structure", "",
328             new Annotation[] {});
329     annotation.setCalcId("JMOL");
330     annotation.visible = false;
331     seqs.get(0).addAlignmentAnnotation(annotation);
332     parentPanel.getAlignment().addAnnotation(annotation);
333
334     // Jpred.SSP on Sequence0 - hidden
335     annotation = new AlignmentAnnotation("SSP", "", new Annotation[] {});
336     annotation.setCalcId("JPred");
337     annotation.visible = false;
338     seqs.get(0).addAlignmentAnnotation(annotation);
339     parentPanel.getAlignment().addAnnotation(annotation);
340
341     // PDB.Temp on Sequence1
342     annotation = new AlignmentAnnotation("Temp", "", new Annotation[] {});
343     annotation.setCalcId("PDB");
344     annotation.visible = true;
345     seqs.get(1).addAlignmentAnnotation(annotation);
346     parentPanel.getAlignment().addAnnotation(annotation);
347
348     /*
349      * Expect menu options to show "secondary structure" and "SSP", and to hide
350      * "secondary structure" and "Temp". Tooltip should be calcId.
351      */
352     testee.buildAnnotationTypesMenus(showMenu, hideMenu, seqs);
353
354     assertTrue(showMenu.isEnabled());
355     assertTrue(hideMenu.isEnabled());
356
357     Component[] showOptions = showMenu.getMenuComponents();
358     Component[] hideOptions = hideMenu.getMenuComponents();
359
360     assertEquals(4, showOptions.length); // includes 'All' and separator
361     assertEquals(4, hideOptions.length);
362     String all = MessageManager.getString("label.all");
363     assertEquals(all, ((JMenuItem) showOptions[0]).getText());
364     assertTrue(showOptions[1] instanceof JPopupMenu.Separator);
365     assertEquals(JSeparator.HORIZONTAL,
366             ((JSeparator) showOptions[1]).getOrientation());
367     assertEquals("secondary structure",
368             ((JMenuItem) showOptions[2]).getText());
369     assertEquals("JMOL", ((JMenuItem) showOptions[2]).getToolTipText());
370     assertEquals("SSP", ((JMenuItem) showOptions[3]).getText());
371     assertEquals("JPred", ((JMenuItem) showOptions[3]).getToolTipText());
372
373     assertEquals(all, ((JMenuItem) hideOptions[0]).getText());
374     assertTrue(hideOptions[1] instanceof JPopupMenu.Separator);
375     assertEquals(JSeparator.HORIZONTAL,
376             ((JSeparator) hideOptions[1]).getOrientation());
377     assertEquals("secondary structure",
378             ((JMenuItem) hideOptions[2]).getText());
379     assertEquals("PDB", ((JMenuItem) hideOptions[2]).getToolTipText());
380     assertEquals("Temp", ((JMenuItem) hideOptions[3]).getText());
381     assertEquals("PDB", ((JMenuItem) hideOptions[3]).getToolTipText());
382   }
383
384   /**
385    * Test for building menu options with only 'hide' annotation types enabled.
386    */
387   @Test(groups = { "Functional" })
388   public void testBuildAnnotationTypesMenus_showDisabled()
389   {
390     JMenu showMenu = new JMenu();
391     JMenu hideMenu = new JMenu();
392     List<SequenceI> seqs = parentPanel.getAlignment().getSequences();
393
394     // make up new annotations and add to sequences and to the alignment
395
396     // PDB.secondary structure on Sequence0
397     AlignmentAnnotation annotation = new AlignmentAnnotation(
398             "secondary structure", "", new Annotation[] {});
399     annotation.setCalcId("PDB");
400     annotation.visible = true;
401     seqs.get(0).addAlignmentAnnotation(annotation);
402     parentPanel.getAlignment().addAnnotation(annotation);
403
404     // PDB.Temp on Sequence1
405     annotation = new AlignmentAnnotation("Temp", "", new Annotation[] {});
406     annotation.setCalcId("PDB");
407     annotation.visible = true;
408     seqs.get(1).addAlignmentAnnotation(annotation);
409     parentPanel.getAlignment().addAnnotation(annotation);
410
411     /*
412      * Expect menu options to hide "secondary structure" and "Temp". Tooltip
413      * should be calcId. 'Show' menu should be disabled.
414      */
415     testee.buildAnnotationTypesMenus(showMenu, hideMenu, seqs);
416
417     assertFalse(showMenu.isEnabled());
418     assertTrue(hideMenu.isEnabled());
419
420     Component[] showOptions = showMenu.getMenuComponents();
421     Component[] hideOptions = hideMenu.getMenuComponents();
422
423     assertEquals(2, showOptions.length); // includes 'All' and separator
424     assertEquals(4, hideOptions.length);
425     String all = MessageManager.getString("label.all");
426     assertEquals(all, ((JMenuItem) showOptions[0]).getText());
427     assertTrue(showOptions[1] instanceof JPopupMenu.Separator);
428     assertEquals(JSeparator.HORIZONTAL,
429             ((JSeparator) showOptions[1]).getOrientation());
430
431     assertEquals(all, ((JMenuItem) hideOptions[0]).getText());
432     assertTrue(hideOptions[1] instanceof JPopupMenu.Separator);
433     assertEquals(JSeparator.HORIZONTAL,
434             ((JSeparator) hideOptions[1]).getOrientation());
435     assertEquals("secondary structure",
436             ((JMenuItem) hideOptions[2]).getText());
437     assertEquals("PDB", ((JMenuItem) hideOptions[2]).getToolTipText());
438     assertEquals("Temp", ((JMenuItem) hideOptions[3]).getText());
439     assertEquals("PDB", ((JMenuItem) hideOptions[3]).getToolTipText());
440   }
441
442   /**
443    * Test for building menu options with only 'show' annotation types enabled.
444    */
445   @Test(groups = { "Functional" })
446   public void testBuildAnnotationTypesMenus_hideDisabled()
447   {
448     JMenu showMenu = new JMenu();
449     JMenu hideMenu = new JMenu();
450     List<SequenceI> seqs = parentPanel.getAlignment().getSequences();
451
452     // make up new annotations and add to sequences and to the alignment
453
454     // PDB.secondary structure on Sequence0
455     AlignmentAnnotation annotation = new AlignmentAnnotation(
456             "secondary structure", "", new Annotation[] {});
457     annotation.setCalcId("PDB");
458     annotation.visible = false;
459     seqs.get(0).addAlignmentAnnotation(annotation);
460     parentPanel.getAlignment().addAnnotation(annotation);
461
462     // PDB.Temp on Sequence1
463     annotation = new AlignmentAnnotation("Temp", "", new Annotation[] {});
464     annotation.setCalcId("PDB2");
465     annotation.visible = false;
466     seqs.get(1).addAlignmentAnnotation(annotation);
467     parentPanel.getAlignment().addAnnotation(annotation);
468
469     /*
470      * Expect menu options to show "secondary structure" and "Temp". Tooltip
471      * should be calcId. 'hide' menu should be disabled.
472      */
473     testee.buildAnnotationTypesMenus(showMenu, hideMenu, seqs);
474
475     assertTrue(showMenu.isEnabled());
476     assertFalse(hideMenu.isEnabled());
477
478     Component[] showOptions = showMenu.getMenuComponents();
479     Component[] hideOptions = hideMenu.getMenuComponents();
480
481     assertEquals(4, showOptions.length); // includes 'All' and separator
482     assertEquals(2, hideOptions.length);
483     String all = MessageManager.getString("label.all");
484     assertEquals(all, ((JMenuItem) showOptions[0]).getText());
485     assertTrue(showOptions[1] instanceof JPopupMenu.Separator);
486     assertEquals(JSeparator.HORIZONTAL,
487             ((JSeparator) showOptions[1]).getOrientation());
488     assertEquals("secondary structure",
489             ((JMenuItem) showOptions[2]).getText());
490     assertEquals("PDB", ((JMenuItem) showOptions[2]).getToolTipText());
491     assertEquals("Temp", ((JMenuItem) showOptions[3]).getText());
492     assertEquals("PDB2", ((JMenuItem) showOptions[3]).getToolTipText());
493
494     assertEquals(all, ((JMenuItem) hideOptions[0]).getText());
495     assertTrue(hideOptions[1] instanceof JPopupMenu.Separator);
496     assertEquals(JSeparator.HORIZONTAL,
497             ((JSeparator) hideOptions[1]).getOrientation());
498   }
499
500   /**
501    * Test for adding sequence id, dbref and feature links
502    */
503   @Test(groups = { "Functional" })
504   public void testBuildLinkMenu()
505   {
506     List<SequenceI> seqs = parentPanel.getAlignment().getSequences();
507     final SequenceI seq0 = seqs.get(0);
508     final SequenceI seq1 = seqs.get(1);
509     final List<SequenceFeature> noFeatures = Collections
510             .<SequenceFeature> emptyList();
511     final String linkText = MessageManager.getString("action.link");
512
513     seq0.addDBRef(new DBRefEntry(DBRefSource.UNIPROT, "1", "P83527"));
514     seq0.addDBRef(new DBRefEntry("INTERPRO", "1", "IPR001041"));
515     seq0.addDBRef(new DBRefEntry("INTERPRO", "1", "IPR012675"));
516     seq0.addDBRef(new DBRefEntry("INTERPRO", "1", "IPR006058"));
517     seq1.addDBRef(new DBRefEntry(DBRefSource.UNIPROT, "1", "Q9ZTS2"));
518     seq1.addDBRef(new DBRefEntry("GENE3D", "1", "3.10.20.30"));
519     
520     /*
521      * check the Link Menu for the first sequence
522      */
523     JMenu linkMenu = PopupMenu.buildLinkMenu(seq0, noFeatures);
524     assertEquals(linkText, linkMenu.getText());
525     Component[] linkItems = linkMenu.getMenuComponents();
526     
527     /*
528      * menu items are ordered: SEQUENCE_ID search first, then dbrefs in order
529      * of database name (and within that by order of dbref addition)
530      */
531     assertEquals(5, linkItems.length);
532     assertEquals("EMBL-EBI Search", ((JMenuItem) linkItems[0]).getText());
533     assertEquals("INTERPRO|IPR001041",
534             ((JMenuItem) linkItems[1]).getText());
535     assertEquals("INTERPRO|IPR012675",
536             ((JMenuItem) linkItems[2]).getText());
537     assertEquals("INTERPRO|IPR006058",
538             ((JMenuItem) linkItems[3]).getText());
539     assertEquals("UNIPROT|P83527", ((JMenuItem) linkItems[4]).getText());
540
541     /*
542      * check the Link Menu for the second sequence
543      * note dbref GENE3D is matched to link Gene3D, the latter is displayed
544      */
545     linkMenu = PopupMenu.buildLinkMenu(seq1, noFeatures);
546     linkItems = linkMenu.getMenuComponents();
547     assertEquals(3, linkItems.length);
548     assertEquals("EMBL-EBI Search", ((JMenuItem) linkItems[0]).getText());
549     assertEquals("Gene3D|3.10.20.30", ((JMenuItem) linkItems[1]).getText());
550     assertEquals("UNIPROT|Q9ZTS2", ((JMenuItem) linkItems[2]).getText());
551
552     /*
553      * if there are no valid links the Links submenu is still shown, but
554      * reduced to the EMBL-EBI lookup only (inserted by 
555      * CustomUrlProvider.choosePrimaryUrl())
556      */
557     String unmatched = "NOMATCH|http://www.uniprot.org/uniprot/$"
558             + DB_ACCESSION + "$";
559     UrlProviderFactoryI factory = new DesktopUrlProviderFactory(null,
560             unmatched, "");
561     Preferences.sequenceUrlLinks = factory.createUrlProvider();
562
563     linkMenu = PopupMenu.buildLinkMenu(seq1, noFeatures);
564     linkItems = linkMenu.getMenuComponents();
565     assertEquals(1, linkItems.length);
566     assertEquals("EMBL-EBI Search", ((JMenuItem) linkItems[0]).getText());
567
568     /*
569      * if sequence is null, only feature links are shown (alignment popup submenu)
570      */
571     linkMenu = PopupMenu.buildLinkMenu(null, noFeatures);
572     linkItems = linkMenu.getMenuComponents();
573     assertEquals(0, linkItems.length);
574
575     List<SequenceFeature> features = new ArrayList<>();
576     SequenceFeature sf = new SequenceFeature("type", "desc", 1, 20, null);
577     features.add(sf);
578     linkMenu = PopupMenu.buildLinkMenu(null, features);
579     linkItems = linkMenu.getMenuComponents();
580     assertEquals(0, linkItems.length); // feature has no links
581
582     sf.addLink("Pfam family|http://pfam.xfam.org/family/PF00111");
583     linkMenu = PopupMenu.buildLinkMenu(null, features);
584     linkItems = linkMenu.getMenuComponents();
585     assertEquals(1, linkItems.length);
586     JMenuItem item = (JMenuItem) linkItems[0];
587     assertEquals("Pfam family", item.getText());
588     // ? no way to verify URL, compiled into link's actionListener
589   }
590
591   @Test(groups = { "Functional" })
592   public void testHideInsertions()
593   {
594     // get sequences from the alignment
595     List<SequenceI> seqs = parentPanel.getAlignment().getSequences();
596     
597     // add our own seqs to avoid problems with changes to existing sequences
598     // (gap at end of sequences varies depending on how tests are run!)
599     Sequence seqGap1 = new Sequence("GappySeq",
600             "AAAA----AA-AAAAAAA---AAA-----------AAAAAAAAAA--");
601     seqGap1.createDatasetSequence();
602     seqs.add(seqGap1);
603     Sequence seqGap2 = new Sequence("LessGappySeq",
604             "AAAAAA-AAAAA---AAA--AAAAA--AAAAAAA-AAAAAA");
605     seqGap2.createDatasetSequence();
606     seqs.add(seqGap2);
607     Sequence seqGap3 = new Sequence("AnotherGapSeq",
608             "AAAAAA-AAAAAA--AAAAAA-AAAAAAAAAAA---AAAAAAAA");
609     seqGap3.createDatasetSequence();
610     seqs.add(seqGap3);
611     Sequence seqGap4 = new Sequence("NoGaps",
612             "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA");
613     seqGap4.createDatasetSequence();
614     seqs.add(seqGap4);
615
616     ColumnSelection sel = new ColumnSelection();
617     parentPanel.av.getAlignment().getHiddenColumns()
618             .revealAllHiddenColumns(sel);
619
620     // get the Popup Menu for 7th sequence - no insertions
621     testee = new PopupMenu(parentPanel, seqs.get(7), null);
622     testee.hideInsertions_actionPerformed(null);
623     
624     HiddenColumns hidden = parentPanel.av.getAlignment().getHiddenColumns();
625     Iterator<int[]> it = hidden.iterator();
626     assertFalse(it.hasNext());
627
628     // get the Popup Menu for GappySeq - this time we have insertions
629     testee = new PopupMenu(parentPanel, seqs.get(4), null);
630     testee.hideInsertions_actionPerformed(null);
631     hidden = parentPanel.av.getAlignment().getHiddenColumns();
632     it = hidden.iterator();
633
634     assertTrue(it.hasNext());
635     int[] region = it.next();
636     assertEquals(region[0], 4);
637     assertEquals(region[1], 7);
638
639     assertTrue(it.hasNext());
640     region = it.next();
641     assertEquals(region[0], 10);
642     assertEquals(region[1], 10);
643
644     assertTrue(it.hasNext());
645     region = it.next();
646     assertEquals(region[0], 18);
647     assertEquals(region[1], 20);
648
649     assertTrue(it.hasNext());
650     region = it.next();
651     assertEquals(region[0], 24);
652     assertEquals(region[1], 34);
653
654     assertTrue(it.hasNext());
655     region = it.next();
656     assertEquals(region[0], 45);
657     assertEquals(region[1], 46);
658
659     assertFalse(it.hasNext());
660
661     sel = new ColumnSelection();
662     hidden.revealAllHiddenColumns(sel);
663
664     // make a sequence group and hide insertions within the group
665     SequenceGroup sg = new SequenceGroup();
666     sg.setStartRes(8);
667     sg.setEndRes(42);
668     sg.addSequence(seqGap2, false);
669     sg.addSequence(seqGap3, false);
670     parentPanel.av.setSelectionGroup(sg);
671
672     // hide columns outside and within selection
673     // only hidden columns outside the collection will be retained (unless also
674     // gaps in the selection)
675     hidden.hideColumns(1, 10);
676     hidden.hideColumns(31, 40);
677
678     // get the Popup Menu for LessGappySeq in the sequence group
679     testee = new PopupMenu(parentPanel, seqs.get(5), null);
680     testee.hideInsertions_actionPerformed(null);
681     hidden = parentPanel.av.getAlignment().getHiddenColumns();
682     it = hidden.iterator();
683
684     assertTrue(it.hasNext());
685     region = it.next();
686     assertEquals(region[0], 1);
687     assertEquals(region[1], 7);
688
689     assertTrue(it.hasNext());
690     region = it.next();
691     assertEquals(region[0], 13);
692     assertEquals(region[1], 14);
693
694     assertTrue(it.hasNext());
695     region = it.next();
696     assertEquals(region[0], 34);
697     assertEquals(region[1], 34);
698   }
699
700 }