JAL-2505 removed SequenceFeature constructor JAL-1641 include
[jalview.git] / test / jalview / io / JSONFileTest.java
index ec3f77b..17982be 100644 (file)
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ * 
+ * This file is part of Jalview.
+ * 
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License 
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *  
+ * Jalview is distributed in the hope that it will be useful, but 
+ * WITHOUT ANY WARRANTY; without even the implied warranty 
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+ * PURPOSE.  See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
 package jalview.io;
 
-
 import static org.testng.AssertJUnit.assertNotNull;
-import org.testng.annotations.AfterMethod;
-import org.testng.annotations.Test;
-import org.testng.annotations.BeforeMethod;
-import org.testng.AssertJUnit;
+
+import jalview.api.AlignExportSettingI;
 import jalview.datamodel.Alignment;
 import jalview.datamodel.AlignmentAnnotation;
 import jalview.datamodel.AlignmentI;
 import jalview.datamodel.Annotation;
+import jalview.datamodel.HiddenColumns;
 import jalview.datamodel.Sequence;
 import jalview.datamodel.SequenceFeature;
 import jalview.datamodel.SequenceGroup;
 import jalview.datamodel.SequenceI;
+import jalview.datamodel.features.SequenceFeatures;
 import jalview.gui.AlignFrame;
-import jalview.gui.AlignmentPanel;
+import jalview.gui.JvOptionPane;
+import jalview.json.binding.biojson.v1.ColourSchemeMapper;
 import jalview.schemes.ColourSchemeI;
-import jalview.viewmodel.seqfeatures.FeaturesDisplayed;
+import jalview.schemes.ResidueColourScheme;
 
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.testng.Assert;
+import org.testng.AssertJUnit;
+import org.testng.annotations.AfterTest;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.BeforeTest;
+import org.testng.annotations.Test;
 
 public class JSONFileTest
 {
 
+  @BeforeClass(alwaysRun = true)
+  public void setUpJvOptionPane()
+  {
+    JvOptionPane.setInteractiveMode(false);
+    JvOptionPane.setMockResponse(JvOptionPane.CANCEL_OPTION);
+  }
+
   private int TEST_SEQ_HEIGHT = 0;
 
   private int TEST_GRP_HEIGHT = 0;
 
   private int TEST_ANOT_HEIGHT = 0;
 
-  private AlignFrame af;
+  private int TEST_CS_HEIGHT = 0;
+
+  private String TEST_JSON_FILE = "examples/example.json";
+
+  private Alignment alignment;
+
+  private HashMap<String, SequenceI> expectedSeqs = new HashMap<String, SequenceI>();
+
+  private HashMap<String, AlignmentAnnotation> expectedAnnots = new HashMap<String, AlignmentAnnotation>();
+
+  private HashMap<String, SequenceGroup> expectedGrps = new HashMap<String, SequenceGroup>();
+
+  private HiddenColumns expectedColSel = new HiddenColumns();
 
-  AlignmentI alignment;
+  private SequenceI[] expectedHiddenSeqs = new SequenceI[1];
 
-  AlignmentPanel alignPanel;
+  private AlignmentI testAlignment;
 
-  HashMap<String, SequenceI> testSeqs = new HashMap<String, SequenceI>();
-  HashMap<String, AlignmentAnnotation> testAnnots = new HashMap<String, AlignmentAnnotation>();
-  HashMap<String, SequenceGroup> testGrps = new HashMap<String, SequenceGroup>();
+  private int passedCount;
 
-  @BeforeMethod
+  private JSONFile testJsonFile;
+
+  private JSONFile jf;
+
+  private AlignExportSettingI exportSettings;
+
+  @BeforeTest(alwaysRun = true)
   public void setup() throws Exception
   {
+    /*
+     * construct expected values
+     * nb this have to match the data in examples/example.json
+     */
     // create and add sequences
     Sequence[] seqs = new Sequence[5];
     seqs[0] = new Sequence("FER_CAPAN",
@@ -58,43 +115,47 @@ public class JSONFileTest
     seqs[4] = new Sequence("Q7XA98_TRIPR",
             "ALYGTAVSTSFMRRQPVPMSV-ATTTTTKAFPSGF", 6, 39);
 
+    SequenceI hiddenSeq = new Sequence("FER_TOCH",
+            "FILGTMISKSFLFRKPAVTSL-KAISNVGE--ALF", 3, 34);
+    expectedHiddenSeqs[0] = hiddenSeq;
+
     // create and add sequence features
     SequenceFeature seqFeature2 = new SequenceFeature("feature_x",
-            "desciption", "status", 6, 15, "Jalview");
+            "theDesc", 6, 15, "Jalview");
     SequenceFeature seqFeature3 = new SequenceFeature("feature_x",
-            "desciption", "status", 9, 18, "Jalview");
+            "theDesc", 9, 18, "Jalview");
     SequenceFeature seqFeature4 = new SequenceFeature("feature_x",
-            "desciption", "status", 9, 18, "Jalview");
+            "theDesc", 9, 18, "Jalview");
+    // non-positional feature:
+    SequenceFeature seqFeature5 = new SequenceFeature("Domain",
+            "My description", 0, 0, "Pfam");
     seqs[2].addSequenceFeature(seqFeature2);
     seqs[3].addSequenceFeature(seqFeature3);
     seqs[4].addSequenceFeature(seqFeature4);
-
-    // add created features to features displayed
-    FeaturesDisplayed fDis = new FeaturesDisplayed();
-    fDis.setVisible("feature_x");
-    // jsonFile.setDisplayedFeatures(fDis);
-    // jsonFile.setShowSeqFeatures(true);
+    seqs[2].addSequenceFeature(seqFeature5);
 
     for (Sequence seq : seqs)
     {
-      seq.setDatasetSequence(seq);
-      testSeqs.put(seq.getName(), seq);
-      // jsonFile.seqs.add(seq);
+      seq.createDatasetSequence();
+      expectedSeqs.put(seq.getName(), seq);
     }
 
-    // create and add sequence groups
-    ArrayList<SequenceI> grpSeqs = new ArrayList<SequenceI>();
+    // create and add a sequence group
+    List<SequenceI> grpSeqs = new ArrayList<SequenceI>();
     grpSeqs.add(seqs[1]);
     grpSeqs.add(seqs[2]);
     grpSeqs.add(seqs[3]);
     grpSeqs.add(seqs[4]);
-    ColourSchemeI scheme = JSONFile.getJalviewColorScheme("zappo");
-    SequenceGroup seqGrp = new SequenceGroup(grpSeqs, "JGroup:1883305585",
-            scheme, true, true, false, 21, 29);
+    SequenceGroup seqGrp = new SequenceGroup(grpSeqs,
+            "JGroup:1883305585",
+            null, true, true, false, 21, 29);
+    ColourSchemeI scheme = ColourSchemeMapper.getJalviewColourScheme(
+            "zappo", seqGrp);
+    seqGrp.cs.setColourScheme(scheme);
     seqGrp.setShowNonconserved(false);
     seqGrp.setDescription(null);
-    // jsonFile.seqGroups.add(seqGrp);
-    testGrps.put(seqGrp.getName(), seqGrp);
+
+    expectedGrps.put(seqGrp.getName(), seqGrp);
 
     // create and add annotation
     Annotation[] annot = new Annotation[35];
@@ -136,51 +197,226 @@ public class JSONFileTest
 
     AlignmentAnnotation alignAnnot = new AlignmentAnnotation(
             "Secondary Structure", "New description", annot);
-    // jsonFile.annotations.add(alignAnnot);
-    testAnnots.put(alignAnnot.label, alignAnnot);
+    expectedAnnots.put(alignAnnot.label, alignAnnot);
 
-    // Alignment al = new Alignment(seqs);
-    TEST_SEQ_HEIGHT = testSeqs.size();
-    TEST_GRP_HEIGHT = testGrps.size();
-    TEST_ANOT_HEIGHT = testAnnots.size();
-  }
+    expectedColSel.hideColumns(32, 33);
+    expectedColSel.hideColumns(34, 34);
 
-  @AfterMethod
-  public void tearDown() throws Exception
-  {
-  }
+    TEST_SEQ_HEIGHT = expectedSeqs.size();
+    TEST_GRP_HEIGHT = expectedGrps.size();
+    TEST_ANOT_HEIGHT = expectedAnnots.size();
+    TEST_CS_HEIGHT = expectedColSel.getHiddenRegions().size();
 
-  @Test
-  public void testParse()
-  {
-    String jsonFile = "examples/example.json";
-    AppletFormatAdapter rf = new AppletFormatAdapter();
-    Alignment al = null;
+    exportSettings = new AlignExportSettingI()
+    {
+      @Override
+      public boolean isExportHiddenSequences()
+      {
+        return true;
+      }
+
+      @Override
+      public boolean isExportHiddenColumns()
+      {
+        return true;
+      }
+
+      @Override
+      public boolean isExportGroups()
+      {
+        return true;
+      }
+
+      @Override
+      public boolean isExportFeatures()
+      {
+        return true;
+      }
+
+      @Override
+      public boolean isExportAnnotations()
+      {
+        return true;
+      }
+
+      @Override
+      public boolean isCancelled()
+      {
+        return false;
+      }
+    };
+
+    AppletFormatAdapter formatAdapter = new AppletFormatAdapter();
     try
     {
-      al = rf.readFile(jsonFile, AppletFormatAdapter.FILE,
-              JSONFile.FILE_DESC);
+      alignment = (Alignment) formatAdapter.readFile(TEST_JSON_FILE,
+              DataSourceType.FILE, FileFormat.Json);
+      jf = (JSONFile) formatAdapter.getAlignFile();
+
+      AlignFrame af = new AlignFrame(alignment, jf.getHiddenSequences(),
+              jf.getHiddenColumns(), AlignFrame.DEFAULT_WIDTH,
+              AlignFrame.DEFAULT_HEIGHT);
+      af.getViewport().setShowSequenceFeatures(jf.isShowSeqFeatures());
+      String colourSchemeName = jf.getGlobalColourScheme();
+      ColourSchemeI cs = ColourSchemeMapper.getJalviewColourScheme(
+              colourSchemeName, alignment);
+      af.changeColour(cs);
+      af.getViewport().setFeaturesDisplayed(jf.getDisplayedFeatures());
+
+      formatAdapter = new AppletFormatAdapter(af.alignPanel, exportSettings);
+      String jsonOutput = formatAdapter.formatSequences(FileFormat.Json,
+              af.alignPanel.getAlignment(), false);
+
+      formatAdapter = new AppletFormatAdapter();
+      testAlignment = formatAdapter.readFile(jsonOutput,
+              DataSourceType.PASTE, FileFormat.Json);
+      testJsonFile = (JSONFile) formatAdapter.getAlignFile();
+      // System.out.println(jsonOutput);
     } catch (IOException e)
     {
       e.printStackTrace();
     }
-    assertNotNull("Couldn't read supplied alignment data.", al);
 
-    int passedCount = 0;
-    for (SequenceI seq : al.getSequences())
+  }
+
+  @BeforeMethod(alwaysRun = true)
+  public void methodSetup()
+  {
+    passedCount = 0;
+  }
+
+  @AfterTest(alwaysRun = true)
+  public void tearDown() throws Exception
+  {
+    testJsonFile = null;
+    alignment = null;
+    expectedSeqs = null;
+    expectedAnnots = null;
+    expectedGrps = null;
+    testAlignment = null;
+    jf = null;
+  }
+
+  @Test(groups = { "Functional" })
+  public void roundTripTest()
+  {
+    assertNotNull("JSON roundtrip test failed!", testJsonFile);
+  }
+
+  @Test(groups = { "Functional" })
+  public void testSeqParsed()
+  {
+    assertNotNull("Couldn't read supplied alignment data.", testAlignment);
+    Assert.assertNotNull(testAlignment.getSequences());
+    for (SequenceI seq : testAlignment.getSequences())
     {
-      SequenceI expectedSeq = testSeqs.get(seq.getName());
-      AssertJUnit.assertTrue("Failed Sequence Test  for >>> " + seq.getName(),
+      SequenceI expectedSeq = expectedSeqs.get(seq.getName());
+      AssertJUnit.assertTrue(
+              "Failed Sequence Test  for >>> " + seq.getName(),
               isSeqMatched(expectedSeq, seq));
       passedCount++;
     }
     AssertJUnit.assertEquals("Some Sequences did not pass the test",
             TEST_SEQ_HEIGHT, passedCount);
+  }
 
-    passedCount = 0;
-    for (SequenceGroup seqGrp : al.getGroups())
+  @Test(groups = { "Functional" })
+  public void hiddenColsTest()
+  {
+    HiddenColumns cs = testJsonFile.getHiddenColumns();
+    Assert.assertNotNull(cs);
+    Assert.assertNotNull(cs.getHiddenRegions());
+    List<int[]> hiddenCols = cs.getHiddenRegions();
+    Assert.assertEquals(hiddenCols.size(), TEST_CS_HEIGHT);
+    Assert.assertEquals(hiddenCols.get(0), expectedColSel
+            .getHiddenRegions().get(0),
+            "Mismatched hidden columns!");
+  }
+
+  @Test(groups = { "Functional" })
+  public void hiddenSeqsTest()
+  {
+    Assert.assertNotNull(testJsonFile.getHiddenSequences(),
+            "Hidden sequence Expected but found Null");
+    Assert.assertEquals(jf.getHiddenSequences().length, 1,
+            "Hidden sequence");
+  }
+
+  @Test(groups = { "Functional" })
+  public void colorSchemeTest()
+  {
+    Assert.assertNotNull(testJsonFile.getGlobalColourScheme(),
+            "Colourscheme is null, parsing failed!");
+    Assert.assertEquals(testJsonFile.getGlobalColourScheme(), "Zappo",
+            "Zappo colour scheme expected!");
+  }
+
+  /**
+   * Test for bug JAL-2489, NPE when exporting BioJSON with global colour
+   * scheme, and a group colour scheme, set as 'None'
+   */
+  @Test(groups = { "Functional" })
+  public void testBioJSONRoundTripWithColourSchemeNone()
+  {
+    AppletFormatAdapter formatAdapter = new AppletFormatAdapter();
+
+    Alignment _alignment;
+    try
     {
-      SequenceGroup expectedGrp = testGrps.get(seqGrp.getName());
+      // load example BioJSON file
+      _alignment = (Alignment) formatAdapter.readFile(TEST_JSON_FILE,
+              DataSourceType.FILE, FileFormat.Json);
+      JSONFile bioJsonFile = (JSONFile) formatAdapter.getAlignFile();
+      AlignFrame alignFrame = new AlignFrame(_alignment,
+              bioJsonFile.getHiddenSequences(),
+              bioJsonFile.getHiddenColumns(), AlignFrame.DEFAULT_WIDTH,
+              AlignFrame.DEFAULT_HEIGHT);
+
+      /*
+       * Create a group on the alignment;
+       * Change global and group colour scheme to 'None' and perform round trip
+       */
+      SequenceGroup sg = new SequenceGroup();
+      sg.addSequence(_alignment.getSequenceAt(0), false);
+      sg.setColourScheme(null);
+      ColourSchemeI cs = ColourSchemeMapper.getJalviewColourScheme(
+              ResidueColourScheme.NONE, _alignment);
+      alignFrame.changeColour(cs);
+      alignFrame.getViewport().setFeaturesDisplayed(
+              bioJsonFile.getDisplayedFeatures());
+      formatAdapter = new AppletFormatAdapter(alignFrame.alignPanel,
+              exportSettings);
+      // export BioJSON string
+      String jsonOutput = formatAdapter.formatSequences(FileFormat.Json,
+              alignFrame.alignPanel.getAlignment(), false);
+      // read back Alignment from BioJSON string
+      formatAdapter = new AppletFormatAdapter();
+      formatAdapter.readFile(jsonOutput, DataSourceType.PASTE,
+              FileFormat.Json);
+      // assert 'None' colour scheme is retained after round trip
+      JSONFile _bioJsonFile = (JSONFile) formatAdapter.getAlignFile();
+      Assert.assertEquals(_bioJsonFile.getGlobalColourScheme(),
+              ResidueColourScheme.NONE);
+    } catch (IOException e)
+    {
+      e.printStackTrace();
+    }
+  }
+
+  @Test(groups = { "Functional" })
+  public void isShowSeqFeaturesSet()
+  {
+    Assert.assertTrue(testJsonFile.isShowSeqFeatures(),
+            "Sequence feature isDisplayed setting expected to be true");
+  }
+
+  @Test(groups = { "Functional" })
+  public void testGrpParsed()
+  {
+    Assert.assertNotNull(testAlignment.getGroups());
+    for (SequenceGroup seqGrp : testAlignment.getGroups())
+    {
+      SequenceGroup expectedGrp = expectedGrps.get(seqGrp.getName());
       AssertJUnit.assertTrue(
               "Failed SequenceGroup Test for >>> " + seqGrp.getName(),
               isGroupMatched(expectedGrp, seqGrp));
@@ -188,21 +424,21 @@ public class JSONFileTest
     }
     AssertJUnit.assertEquals("Some SequenceGroups did not pass the test",
             TEST_GRP_HEIGHT, passedCount);
+  }
 
-    passedCount = 0;
-    for (AlignmentAnnotation annot : al.getAlignmentAnnotation())
+  @Test(groups = { "Functional" })
+  public void testAnnotationParsed()
+  {
+    Assert.assertNotNull(testAlignment.getAlignmentAnnotation());
+    for (AlignmentAnnotation annot : testAlignment.getAlignmentAnnotation())
     {
-      AlignmentAnnotation expectedAnnot = testAnnots.get(annot.label);
+      AlignmentAnnotation expectedAnnot = expectedAnnots.get(annot.label);
       AssertJUnit.assertTrue("Failed AlignmentAnnotation Test for >>> "
               + annot.label, isAnnotationMatched(expectedAnnot, annot));
       passedCount++;
     }
     AssertJUnit.assertEquals("Some Sequences did not pass the test",
             TEST_ANOT_HEIGHT, passedCount);
-
-    // af = new AlignFrame(al, 700, 500);
-    // AlignViewport viewport = af.getViewport();
-    // alignPanel = new AlignmentPanel(af, viewport);
   }
 
   public boolean isAnnotationMatched(AlignmentAnnotation eAnnot,
@@ -230,7 +466,7 @@ public class JSONFileTest
     return true;
   }
 
-  public boolean isSeqMatched(SequenceI expectedSeq, SequenceI actualSeq)
+  boolean isSeqMatched(SequenceI expectedSeq, SequenceI actualSeq)
   {
     System.out.println("Testing >>> " + actualSeq.getName());
 
@@ -264,13 +500,19 @@ public class JSONFileTest
             + actualGrp.getStartRes());
     System.out.println(expectedGrp.getEndRes() + " | "
             + actualGrp.getEndRes());
+    System.out.println(expectedGrp.cs.getColourScheme() + " | "
+            + actualGrp.cs.getColourScheme());
 
+    boolean colourSchemeMatches = (expectedGrp.cs.getColourScheme() == null && actualGrp.cs
+            .getColourScheme() == null)
+            || expectedGrp.cs.getColourScheme().getClass()
+                    .equals(actualGrp.cs.getColourScheme().getClass());
     if (expectedGrp.getName().equals(actualGrp.getName())
             && expectedGrp.getColourText() == actualGrp.getColourText()
             && expectedGrp.getDisplayBoxes() == actualGrp.getDisplayBoxes()
             && expectedGrp.getIgnoreGapsConsensus() == actualGrp
                     .getIgnoreGapsConsensus()
-            && expectedGrp.cs.equals(actualGrp.cs)
+            && colourSchemeMatches
             && expectedGrp.getSequences().size() == actualGrp
                     .getSequences().size()
             && expectedGrp.getStartRes() == actualGrp.getStartRes()
@@ -283,7 +525,6 @@ public class JSONFileTest
 
   private boolean featuresMatched(SequenceI seq1, SequenceI seq2)
   {
-    boolean matched = false;
     try
     {
       if (seq1 == null && seq2 == null)
@@ -291,51 +532,137 @@ public class JSONFileTest
         return true;
       }
 
-      SequenceFeature[] inFeature = seq1.getSequenceFeatures();
-      SequenceFeature[] outFeature = seq2.getSequenceFeatures();
+      List<SequenceFeature> inFeature = seq1.getFeatures().getAllFeatures();
+      List<SequenceFeature> outFeature = seq2.getFeatures()
+              .getAllFeatures();
 
-      if (inFeature == null && outFeature == null)
-      {
-        return true;
-      }
-      else if ((inFeature == null && outFeature != null)
-              || (inFeature != null && outFeature == null))
+      if (inFeature.size() != outFeature.size())
       {
+        System.err.println("Feature count in: " + inFeature.size()
+                + ", out: " + outFeature.size());
         return false;
       }
 
-      int testSize = inFeature.length;
-      int matchedCount = 0;
+      SequenceFeatures.sortFeatures(inFeature, true);
+      SequenceFeatures.sortFeatures(outFeature, true);
+      int i = 0;
       for (SequenceFeature in : inFeature)
       {
-        for (SequenceFeature out : outFeature)
+        SequenceFeature out = outFeature.get(i);
+        /*
+        System.out.println(out.getType() + " | " + in.getType());
+        System.out.println(out.getBegin() + " | " + in.getBegin());
+        System.out.println(out.getEnd() + " | " + in.getEnd());
+        */
+        if (!in.equals(out))
         {
-          System.out.println(out.getType() + " | " + in.getType());
-          System.out.println(out.getBegin() + " | " + in.getBegin());
-          System.out.println(out.getEnd() + " | " + in.getEnd());
-
-          if (inFeature.length == outFeature.length
-                  && in.getBegin() == out.getBegin()
-                  && in.getEnd() == out.getEnd()
-                  && in.getScore() == out.getScore()
-                  && in.getFeatureGroup().equals(out.getFeatureGroup())
-                  && in.getType().equals(out.getType()))
-          {
-
-            ++matchedCount;
-          }
+          System.err.println("Mismatch of " + in.toString() + " "
+                  + out.toString());
+          return false;
         }
-      }
-      System.out.println("matched count >>>>>> " + matchedCount);
-      if (testSize == matchedCount)
-      {
-        matched = true;
+        /*
+                if (in.getBegin() == out.getBegin() && in.getEnd() == out.getEnd()
+                        && in.getScore() == out.getScore()
+                        && in.getFeatureGroup().equals(out.getFeatureGroup())
+                        && in.getType().equals(out.getType())
+                        && mapsMatch(in.otherDetails, out.otherDetails))
+                {
+                }
+                else
+                {
+                  System.err.println("Feature[" + i + "] mismatch, in: "
+                          + in.toString() + ", out: "
+                          + outFeature.get(i).toString());
+                  return false;
+                }
+                */
+        i++;
       }
     } catch (Exception e)
     {
       e.printStackTrace();
     }
     // System.out.println(">>>>>>>>>>>>>> features matched : " + matched);
-    return matched;
+    return true;
+  }
+
+  boolean mapsMatch(Map<String, Object> m1, Map<String, Object> m2)
+  {
+    if (m1 == null || m2 == null)
+    {
+      if (m1 != null || m2 != null)
+      {
+        System.err
+                .println("only one SequenceFeature.otherDetails is not null");
+        return false;
+      }
+      else
+      {
+        return true;
+      }
+    }
+    if (m1.size() != m2.size())
+    {
+      System.err.println("otherDetails map different sizes");
+      return false;
+    }
+    for (String key : m1.keySet())
+    {
+      if (!m2.containsKey(key))
+      {
+        System.err.println(key + " in only one otherDetails");
+        return false;
+      }
+      if (m1.get(key) == null && m2.get(key) != null || m1.get(key) != null
+              && m2.get(key) == null || !m1.get(key).equals(m2.get(key)))
+      {
+        System.err.println(key + " values in otherDetails don't match");
+        return false;
+      }
+    }
+    return true;
+  }
+
+  /**
+   * Test group roundtrip with null (None) group colour scheme
+   * 
+   * @throws IOException
+   */
+  @Test(groups = { "Functional" })
+  public void testGrpParsed_colourNone() throws IOException
+  {
+    AlignmentI copy = new Alignment(testAlignment);
+    SequenceGroup sg = testAlignment.getGroups().get(0);
+    SequenceGroup copySg = new SequenceGroup(new ArrayList<SequenceI>(),
+            sg.getName(),
+            null, sg.getDisplayBoxes(), sg.getDisplayText(),
+            sg.getColourText(), sg.getStartRes(), sg.getEndRes());
+    for (SequenceI seq : sg.getSequences())
+    {
+      int seqIndex = testAlignment.findIndex(seq);
+      copySg.addSequence(copy.getSequenceAt(seqIndex), false);
+    }
+    copy.addGroup(copySg);
+
+    AlignFrame af = new AlignFrame(copy, copy.getWidth(), copy.getHeight());
+    AppletFormatAdapter formatAdapter = new AppletFormatAdapter(
+            af.alignPanel);
+    String jsonOutput = formatAdapter.formatSequences(FileFormat.Json,
+            copy, false);
+    formatAdapter = new AppletFormatAdapter();
+    AlignmentI newAlignment = formatAdapter.readFile(jsonOutput,
+            DataSourceType.PASTE, FileFormat.Json);
+
+    Assert.assertNotNull(newAlignment.getGroups());
+    for (SequenceGroup seqGrp : newAlignment.getGroups())
+    {
+      SequenceGroup expectedGrp = copySg;
+      AssertJUnit.assertTrue(
+              "Failed SequenceGroup Test for >>> " + seqGrp.getName(),
+              isGroupMatched(expectedGrp, seqGrp));
+      passedCount++;
+    }
+    AssertJUnit.assertEquals("Some SequenceGroups did not pass the test",
+            TEST_GRP_HEIGHT, passedCount);
   }
 }