TwinePublishedRepairer implements TwineRepairer { @Override public final void repair(final InputStream inputStream, final OutputStream outputStream) { Objects.requireNonNull(inputStream); Objects.requireNonNull(outputStream); try { String input = IOUtils.toString(inputStream, StandardCharsets.UTF_8); Matcher matcher = REGEX_TW_STORYDATA.matcher(input); if(!matcher.find()) throw new TwineRepairFailedException("Input does not contain any <tw-storydata> nodes.", null); String xmlInput = String.format("<tw-storiesdata>%s</tw-storiesdata>", matcher.group()); try (InputStream in = new ByteArrayInputStream(xmlInput.getBytes(StandardCharsets.UTF_8))) { tidy.parse(in, outputStream); } } catch (IOException e) { throw new TwineRepairFailedException("Could not read Twine story file from input stream", e); } } TwinePublishedRepairer(); @Override final void repair(final InputStream inputStream, final OutputStream outputStream);  }
@Test public void repair_HarloweStoryFormat_ReturnsValidTwineXml() throws Exception { ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); try(InputStream inputStream = getClass().getResourceAsStream("/html/harlowe_2.1.html")) { repairer.repair(inputStream, outputStream); } validate(outputStream); Assert.assertTrue(true); outputStream.close(); }
@Test public void repair_SnowmanStoryFormat_ReturnsValidTwineXml() throws Exception { ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); try(InputStream inputStream = getClass().getResourceAsStream("/html/snowman_1.3.0.html")) { repairer.repair(inputStream, outputStream); } validate(outputStream); Assert.assertTrue(true); outputStream.close(); }
@Test public void repair_SpecialCharactersInTitle_ReturnsValidTwineXml() throws Exception { ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); try(InputStream inputStream = getClass().getResourceAsStream("/html/special-character-title.html")) { repairer.repair(inputStream, outputStream); } validate(outputStream); Assert.assertTrue(true); outputStream.close(); }
@Test public void repair_SugarQubeStoryFormat_ReturnsValidTwineXml() throws Exception { ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); try(InputStream inputStream = getClass().getResourceAsStream("/html/sugarcube_2.21.0.html")) { repairer.repair(inputStream, outputStream); } validate(outputStream); Assert.assertTrue(true); outputStream.close(); }
@Test public void repair_StyledStoryFormat_StyleIsCopied() throws Exception { ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); try(InputStream inputStream = getClass().getResourceAsStream("/html/harlowe_2.1.html")) { repairer.repair(inputStream, outputStream); } try(InputStream in = new ByteArrayInputStream(outputStream.toByteArray())) { DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance(); DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder(); Document document = documentBuilder.parse(in); Assert.assertNotNull(document.getElementsByTagName("style")); Node style = document.getElementsByTagName("style").item(0); Assert.assertEquals("\n* { background-color: #ffffff; }\n ", style.getTextContent()); } validate(outputStream); Assert.assertTrue(true); outputStream.close(); }
@Test(expected = NullPointerException.class) public void repair_InputNull_ThrowsNullPointerException() throws Exception { try(OutputStream outputStream = new ByteArrayOutputStream()) { repairer.repair(null, outputStream); } }
@Test(expected = NullPointerException.class) public void repair_OutputNull_ThrowsNullPointerException() throws Exception { try(InputStream inputStream = getClass().getResourceAsStream("/html/harlowe.html")) { repairer.repair(inputStream, null); } }
@Test(expected = IOException.class) public void repair_InputDoesNotExist_ThrowsIOException() throws Exception { File doesNotExist = new File("/html/doesNotExist.xml"); OutputStream outputStream = new ByteArrayOutputStream(); try(InputStream inputStream = new FileInputStream(doesNotExist)) { repairer.repair(inputStream, outputStream); } }
@Test(expected = TwineRepairFailedException.class) public void repair_NoTwStoryData_ThrowsTwineRepairFailedException() throws Exception { try(InputStream inputStream = getClass().getResourceAsStream("/html/without-storydata.html"); OutputStream outputStream = new ByteArrayOutputStream()) { repairer.repair(inputStream, outputStream); } }
@Test(expected = TwineRepairFailedException.class) public void repair_ReadingFromInputStreamFails_ThrowsTwineRepairFailedException() { InputStream mockInputStream = Mockito.mock(InputStream.class); OutputStream mockOutputStream = Mockito.mock(OutputStream.class); repairer.repair(mockInputStream, mockOutputStream); }