package com.github.approval; /* * #%L * approval * %% * Copyright (C) 2014 Nikolavp * %% * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * #L% */ import com.github.approval.converters.Converter; import com.github.approval.converters.Converters; import com.github.approval.converters.DefaultConverter; import com.github.approval.example.Entity; import com.github.approval.utils.FileSystemUtils; import org.hamcrest.CoreMatchers; import org.junit.Assert; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.Mockito; import org.mockito.runners.MockitoJUnitRunner; import java.io.File; import java.io.IOException; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.attribute.FileAttribute; import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.CoreMatchers.is; import static org.junit.Assert.assertThat; import static org.mockito.Mockito.*; @RunWith(MockitoJUnitRunner.class) public class ApprovalTest { @Mock private Reporter reporter; @Mock private FileSystemUtils fileSystemUtils; @Mock private PathMapper pathMapper; @Rule public TestTempFile testFile = new TestTempFile(); byte[] getFileContent(File file) throws IOException { return Files.readAllBytes(file.toPath()); } @Test public void shouldCreateFileForApprovalIfNormalFileIsNotLocatedAndNotifyReporter() throws Exception { //assign File fileForApproval = TestUtils.forApproval(testFile); //act try { new Approval<>(reporter, new DefaultConverter(), null).verify(TestUtils.RAW_VALUE, testFile.file().toPath()); } catch (AssertionError error) { //This is thrown because we didn't approve the file } //assert assertThat(fileForApproval.exists(), is(true)); assertThat(getFileContent(fileForApproval), equalTo(TestUtils.RAW_VALUE)); verify(reporter).approveNew(TestUtils.RAW_VALUE, fileForApproval, testFile.file()); Mockito.verifyNoMoreInteractions(reporter); } @Test(expected = AssertionError.class) public void shouldThrowAssertionError_IfCannotWriteNewApprovalFile() throws Exception { doThrow(new IOException("test error")).when(fileSystemUtils).write(any(Path.class), any(byte[].class)); new Approval<>(reporter, new DefaultConverter(), null, fileSystemUtils).verify(TestUtils.RAW_VALUE, testFile.file().toPath()); } @Test(expected = AssertionError.class) public void shouldThrowAssertionErrorIfCannotReadOldFile() throws Exception { //arrange when(fileSystemUtils.readFully(any(Path.class))).thenThrow(new IOException("read test exception")); testFile.file().createNewFile(); new Approval<>(reporter, new DefaultConverter(), null, fileSystemUtils).verify(TestUtils.RAW_VALUE, testFile.file().toPath()); } @Test(expected = AssertionError.class) public void shouldThrowAnAssertionError_IfItCannotWriteTheNewValueToApprovalFile() throws Exception { //arrange testFile.file().createNewFile(); doThrow(new IOException("cannot create approval file")).when(fileSystemUtils).write(TestUtils.forApproval(testFile).toPath(), TestUtils.RAW_VALUE); new Approval<>(reporter, new DefaultConverter(), null, fileSystemUtils).verify(TestUtils.RAW_VALUE, testFile.file().toPath()); } @Test public void shouldCallTheReporterIfAnOldFileExistsButIsNotTheSame() throws Exception{ String valueWithDifference = TestUtils.VALUE + "difference"; Files.write(testFile.file().toPath(), valueWithDifference.getBytes(StandardCharsets.UTF_8)); new Approval<>(reporter, new DefaultConverter(), null).verify(TestUtils.RAW_VALUE, testFile.file().toPath()); verify(reporter).notTheSame(valueWithDifference.getBytes(StandardCharsets.UTF_8), testFile.file(), TestUtils.RAW_VALUE, TestUtils.forApproval(testFile)); Mockito.verifyNoMoreInteractions(reporter); } @Test public void shouldNotCallTheReporterIfAnOldFileAndIsTheSame() throws Exception{ Files.write(testFile.file().toPath(), TestUtils.RAW_VALUE); new Approval<>(reporter, new DefaultConverter(), null).verify(TestUtils.RAW_VALUE, testFile.file().toPath()); Mockito.verifyNoMoreInteractions(reporter); } @Test public void shouldBeAbleToApproveCustomTypes() throws Exception { //assign @SuppressWarnings("unchecked") Converter<Entity> converter = Mockito.mock(Converter.class); Entity testEntity = new Entity("test", 10); byte[] rawBytes = "test".getBytes(StandardCharsets.UTF_8); when(converter.getRawForm(testEntity)).thenReturn(rawBytes); File fileForApproval = TestUtils.forApproval(testFile); reporter.approveNew(rawBytes, fileForApproval, testFile.file()); //act new Approval<>(reporter, converter, null, fileSystemUtils).verify(testEntity, testFile.file().toPath()); //assert verify(fileSystemUtils).write(fileForApproval.toPath(), rawBytes); } @Test(expected = IllegalStateException.class) public void shouldCreateParentDirectoryForPathIfItDoesntExistAndThrowExceptionOnErrors() throws Exception { //assign final File testFileInTemporaryDir = new File(testFile.file(), "test.txt"); reporter.approveNew(any(byte[].class), any(File.class), any(File.class)); doThrow(new IOException("test exception")).when(fileSystemUtils).createDirectories(Mockito.any(File.class)); //act new Approval<>(reporter, Converters.BOOLEAN, null, fileSystemUtils).verify(true, testFileInTemporaryDir.toPath()); //assert verify(fileSystemUtils).createDirectories(testFile.file()); } @Test public void shouldProperlyUsePathMappersForResolvingVerificationFile() throws Exception { //assign final Path path = Paths.get("parent", "subpath"); //noinspection unchecked when(pathMapper.getPath(any(), any(Path.class))).thenReturn(path); reporter.approveNew(any(byte[].class), any(File.class), any(File.class)); //act new Approval<>(reporter, new DefaultConverter(), pathMapper, fileSystemUtils).verify(TestUtils.RAW_VALUE, testFile.path()); //assert verify(fileSystemUtils).createDirectories(new File("parent")); verify(fileSystemUtils).write(Approval.getApprovalPath(path), TestUtils.RAW_VALUE); } @Test public void shouldCreateAnEmptyResultPathBecauseSomeReportersRequireIt() throws Exception { //act new Approval<>(reporter, new DefaultConverter(), null, fileSystemUtils).verify(TestUtils.RAW_VALUE, testFile.path()); //assert verify(fileSystemUtils).touch(testFile.path()); } @Test(expected = AssertionError.class) public void shouldThrowAnExceptionIfItCannotCreateTheResultPath() throws Exception { //assign doThrow(new IOException("test exception")).when(fileSystemUtils).touch(testFile.path()); //act new Approval<>(reporter, new DefaultConverter(), null, fileSystemUtils).verify(TestUtils.RAW_VALUE, testFile.path()); //assert verify(fileSystemUtils).touch(testFile.path()); } @Test public void shouldChangeTheModificationDateForFileUnderTest() throws Exception { Files.write(testFile.file().toPath(), TestUtils.RAW_VALUE); long currentTimeMillis = System.currentTimeMillis(); boolean b = testFile.file().setLastModified(0); if (!b) { throw new RuntimeException("Couldn't change last modified date for file under test!"); } new Approval<>(reporter, new DefaultConverter(), null).verify(TestUtils.RAW_VALUE, testFile.file().toPath()); boolean fileLastModifiedWithin2SEconds = Math.abs(testFile.file().lastModified() - currentTimeMillis) < 2000; Assert.assertThat(fileLastModifiedWithin2SEconds, CoreMatchers.equalTo(true)); } @Test public void getApprovalPathShouldPreserveExtensionForSyntaxHighlighting() throws Exception { Path approvalPath = Approval.getApprovalPath(Paths.get("test/some/directory/file.txt")); Assert.assertThat(approvalPath.toString(), CoreMatchers.equalTo("test/some/directory/file.forapproval.txt")); approvalPath = Approval.getApprovalPath(Paths.get("test/some/directory.with.dots/file.txt")); Assert.assertThat(approvalPath.toString(), CoreMatchers.equalTo("test/some/directory.with.dots/file.forapproval.txt")); approvalPath = Approval.getApprovalPath(Paths.get("test/some/directory.with.dots/file.withTooBigExtension")); Assert.assertThat(approvalPath.toString(), CoreMatchers.equalTo("test/some/directory.with.dots/file.forapproval.withTooBigExtension")); approvalPath = Approval.getApprovalPath(Paths.get("test/some/directory/fileWithoutExtension")); Assert.assertThat(approvalPath.toString(), CoreMatchers.equalTo("test/some/directory/fileWithoutExtension.forapproval")); approvalPath = Approval.getApprovalPath(Paths.get("test/some/directory.with.dots/fileWithoutExtension")); Assert.assertThat(approvalPath.toString(), CoreMatchers.equalTo("test/some/directory.with.dots/fileWithoutExtension.forapproval")); approvalPath = Approval.getApprovalPath(Paths.get("fileNotInDir")); Assert.assertThat(approvalPath.toString(), CoreMatchers.equalTo("fileNotInDir.forapproval")); approvalPath = Approval.getApprovalPath(Paths.get("fileNotInDir.ext")); Assert.assertThat(approvalPath.toString(), CoreMatchers.equalTo("fileNotInDir.forapproval.ext")); } }