Skip to content

Commit a7ef096

Browse files
Add hasNoExtension to File assertions.
Commonize how to get a file/path extension.
1 parent 5bef9b2 commit a7ef096

13 files changed

+251
-46
lines changed

src/main/java/org/assertj/core/api/AbstractFileAssert.java

+22
Original file line numberDiff line numberDiff line change
@@ -1372,6 +1372,28 @@ public AbstractStringAssert<?> content(Charset charset) {
13721372
return internalContent(charset);
13731373
}
13741374

1375+
/**
1376+
* Verifies that the actual {@code File} has no extension.
1377+
*
1378+
* <p>
1379+
* Example:
1380+
* <pre><code class='java'> // assertions succeed
1381+
* assertThat(new File(&quot;file&quot;)).hasNoExtension();
1382+
* assertThat(new File(&quot;file.&quot;)).hasNoExtension();
1383+
*
1384+
* // assertion fails
1385+
* assertThat(new File(&quot;file.txt&quot;)).hasNoExtension();</code></pre>
1386+
*
1387+
* @return {@code this} assertion object.
1388+
* @throws AssertionError if the actual {@code File} is {@code null}.
1389+
* @throws AssertionError if the actual {@code File} is not a file (ie a directory or does not exist).
1390+
* @throws AssertionError if the actual {@code File} does have an extension.
1391+
*/
1392+
public SELF hasNoExtension() {
1393+
files.assertHasNoExtension(info, actual);
1394+
return myself;
1395+
}
1396+
13751397
// this method was introduced to avoid to avoid double proxying in soft assertions for content()
13761398
private AbstractStringAssert<?> internalContent(Charset charset) {
13771399
files.assertCanRead(info, actual);

src/main/java/org/assertj/core/api/AbstractPathAssert.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -1934,8 +1934,9 @@ public SELF hasExtension(String expectedExtension) {
19341934
*
19351935
* <p>
19361936
* Example:
1937-
* <pre><code class='java'> // assertion succeeds
1937+
* <pre><code class='java'> // assertions succeed
19381938
* assertThat(Paths.get(&quot;file&quot;)).hasNoExtension();
1939+
* assertThat(Paths.get(&quot;file.&quot;)).hasNoExtension();
19391940
*
19401941
* // assertion fails
19411942
* assertThat(Paths.get(&quot;file.txt&quot;)).hasNoExtension();</code></pre>

src/main/java/org/assertj/core/error/ShouldHaveExtension.java

+4
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,10 @@ public static ShouldHaveExtension shouldHaveExtension(Path actual, String expect
4343
return new ShouldHaveExtension(actual, expectedExtension);
4444
}
4545

46+
public static ShouldHaveExtension shouldHaveExtension(File actual, String expectedExtension) {
47+
return new ShouldHaveExtension(actual, expectedExtension);
48+
}
49+
4650
private ShouldHaveExtension(Object actual, String expectedExtension) {
4751
super("%nExpecting%n %s%nto have extension:%n %s%nbut had no extension.", actual, expectedExtension);
4852
}

src/main/java/org/assertj/core/error/ShouldHaveNoExtension.java

+10
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
*/
1313
package org.assertj.core.error;
1414

15+
import java.io.File;
1516
import java.nio.file.Path;
1617

1718
/**
@@ -20,12 +21,21 @@
2021
public class ShouldHaveNoExtension extends BasicErrorMessageFactory {
2122

2223
private static final String PATH_HAS_EXTENSION = "%nExpected actual path:%n %s%n not to have an extension, but extension was: %s";
24+
private static final String FILE_HAS_EXTENSION = "%nExpected actual file:%n %s%n not to have an extension, but extension was: %s";
2325

2426
public static ShouldHaveNoExtension shouldHaveNoExtension(Path actual, String extension) {
2527
return new ShouldHaveNoExtension(actual, extension);
2628
}
2729

30+
public static ShouldHaveNoExtension shouldHaveNoExtension(File actual, String extension) {
31+
return new ShouldHaveNoExtension(actual, extension);
32+
}
33+
2834
private ShouldHaveNoExtension(Path actual, String extension) {
2935
super(PATH_HAS_EXTENSION, actual, extension);
3036
}
37+
38+
private ShouldHaveNoExtension(File actual, String extension) {
39+
super(FILE_HAS_EXTENSION, actual, extension);
40+
}
3141
}

src/main/java/org/assertj/core/internal/Files.java

+13-7
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
import static org.assertj.core.error.ShouldHaveDigest.shouldHaveDigest;
3434
import static org.assertj.core.error.ShouldHaveExtension.shouldHaveExtension;
3535
import static org.assertj.core.error.ShouldHaveName.shouldHaveName;
36+
import static org.assertj.core.error.ShouldHaveNoExtension.shouldHaveNoExtension;
3637
import static org.assertj.core.error.ShouldHaveNoParent.shouldHaveNoParent;
3738
import static org.assertj.core.error.ShouldHaveParent.shouldHaveParent;
3839
import static org.assertj.core.error.ShouldHaveSameContent.shouldHaveSameContent;
@@ -41,6 +42,7 @@
4142
import static org.assertj.core.error.ShouldNotContain.directoryShouldNotContain;
4243
import static org.assertj.core.error.ShouldNotExist.shouldNotExist;
4344
import static org.assertj.core.internal.Digests.digestDiff;
45+
import static org.assertj.core.util.Files.getFileNameExtension;
4446
import static org.assertj.core.util.Lists.list;
4547
import static org.assertj.core.util.Preconditions.checkArgument;
4648

@@ -56,6 +58,7 @@
5658
import java.security.MessageDigest;
5759
import java.security.NoSuchAlgorithmException;
5860
import java.util.List;
61+
import java.util.Optional;
5962
import java.util.function.Predicate;
6063
import java.util.stream.Stream;
6164

@@ -395,9 +398,14 @@ public void assertHasParent(AssertionInfo info, File actual, File expected) {
395398
public void assertHasExtension(AssertionInfo info, File actual, String expected) {
396399
requireNonNull(expected, "The expected extension should not be null.");
397400
assertIsFile(info, actual);
398-
String actualExtension = getFileExtension(actual);
399-
if (expected.equals(actualExtension)) return;
400-
throw failures.failure(info, shouldHaveExtension(actual, actualExtension, expected));
401+
String extension = getFileExtension(actual).orElseThrow(() -> failures.failure(info, shouldHaveExtension(actual, expected)));
402+
if (!expected.equals(extension)) throw failures.failure(info, shouldHaveExtension(actual, extension, expected));
403+
}
404+
405+
public void assertHasNoExtension(AssertionInfo info, File actual) {
406+
assertIsFile(info, actual);
407+
Optional<String> extension = getFileExtension(actual);
408+
if (extension.isPresent()) throw failures.failure(info, shouldHaveNoExtension(actual, extension.get()));
401409
}
402410

403411
/**
@@ -576,10 +584,8 @@ private static void assertNotNull(AssertionInfo info, File actual) {
576584
Objects.instance().assertNotNull(info, actual);
577585
}
578586

579-
private String getFileExtension(File file) {
580-
String name = file.getName();
581-
int dotAt = name.lastIndexOf('.');
582-
return dotAt == -1 ? null : name.substring(dotAt + 1);
587+
private Optional<String> getFileExtension(File file) {
588+
return getFileNameExtension(file.getName());
583589
}
584590

585591
private void verifyIsFile(File expected) {

src/main/java/org/assertj/core/internal/Paths.java

+2-4
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@
4949
import static org.assertj.core.error.ShouldNotContain.directoryShouldNotContain;
5050
import static org.assertj.core.error.ShouldNotExist.shouldNotExist;
5151
import static org.assertj.core.error.ShouldStartWithPath.shouldStartWith;
52+
import static org.assertj.core.util.Files.getFileNameExtension;
5253
import static org.assertj.core.util.Preconditions.checkArgument;
5354

5455
import java.io.IOException;
@@ -477,10 +478,7 @@ public void assertHasNoExtension(AssertionInfo info, Path actual) {
477478

478479
private static Optional<String> getExtension(Path path) {
479480
String fileName = path.getFileName().toString();
480-
int dotAt = fileName.lastIndexOf('.');
481-
if (dotAt == -1) return Optional.empty();
482-
String extension = fileName.substring(dotAt + 1);
483-
return extension.equals("") ? Optional.empty() : Optional.of(extension);
481+
return getFileNameExtension(fileName);
484482
}
485483

486484
}

src/main/java/org/assertj/core/util/Files.java

+10-1
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import java.nio.charset.Charset;
2727
import java.util.ArrayList;
2828
import java.util.List;
29+
import java.util.Optional;
2930
import java.util.UUID;
3031

3132
/**
@@ -35,6 +36,9 @@
3536
* @author Alex Ruiz
3637
*/
3738
public class Files {
39+
40+
private Files() {}
41+
3842
/**
3943
* Returns the names of the files inside the specified directory.
4044
*
@@ -311,6 +315,11 @@ private static void checkArgumentCharsetIsSupported(String charsetName) {
311315
checkArgument(Charset.isSupported(charsetName), "Charset:<'%s'> is not supported on this system", charsetName);
312316
}
313317

314-
private Files() {}
318+
public static Optional<String> getFileNameExtension(String fileName) {
319+
int dotAt = fileName.lastIndexOf('.');
320+
if (dotAt == -1) return Optional.empty();
321+
String extension = fileName.substring(dotAt + 1);
322+
return extension.equals("") ? Optional.empty() : Optional.of(extension);
323+
}
315324

316325
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
/*
2+
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
3+
* the License. You may obtain a copy of the License at
4+
*
5+
* http://www.apache.org/licenses/LICENSE-2.0
6+
*
7+
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
8+
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
9+
* specific language governing permissions and limitations under the License.
10+
*
11+
* Copyright 2012-2021 the original author or authors.
12+
*/
13+
package org.assertj.core.api.file;
14+
15+
import static org.mockito.Mockito.verify;
16+
17+
import org.assertj.core.api.FileAssert;
18+
import org.assertj.core.api.FileAssertBaseTest;
19+
20+
class FileAssert_hasNoExtension_Test extends FileAssertBaseTest {
21+
22+
@Override
23+
protected FileAssert invoke_api_method() {
24+
return assertions.hasNoExtension();
25+
}
26+
27+
@Override
28+
protected void verify_internal_effects() {
29+
verify(files).assertHasNoExtension(getInfo(assertions), getActual(assertions));
30+
}
31+
32+
}

src/test/java/org/assertj/core/error/ShouldHaveNoExtension_create_Test.java

+18-2
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import static org.assertj.core.presentation.StandardRepresentation.STANDARD_REPRESENTATION;
1919
import static org.mockito.Mockito.mock;
2020

21+
import java.io.File;
2122
import java.nio.file.Path;
2223

2324
import org.assertj.core.internal.TestDescription;
@@ -28,7 +29,7 @@ class ShouldHaveNoExtension_create_Test {
2829
private static final TestDescription TEST_DESCRIPTION = new TestDescription("Test");
2930

3031
@Test
31-
void should_create_error_message() {
32+
void should_create_error_message_for_path() {
3233
// GIVEN
3334
final Path path = mock(Path.class);
3435
// WHEN
@@ -37,6 +38,21 @@ void should_create_error_message() {
3738
then(actualMessage).isEqualTo(format("[Test] %n" +
3839
"Expected actual path:%n" +
3940
" %s%n" +
40-
" not to have an extension, but extension was: \"java\"", path));
41+
" not to have an extension, but extension was: \"java\"",
42+
STANDARD_REPRESENTATION.toStringOf(path)));
43+
}
44+
45+
@Test
46+
void should_create_error_message_for_file() {
47+
// GIVEN
48+
final File file = new File("foo.java");
49+
// WHEN
50+
String actualMessage = shouldHaveNoExtension(file, "java").create(TEST_DESCRIPTION, STANDARD_REPRESENTATION);
51+
// THEN
52+
then(actualMessage).isEqualTo(format("[Test] %n" +
53+
"Expected actual file:%n" +
54+
" %s%n" +
55+
" not to have an extension, but extension was: \"java\"",
56+
STANDARD_REPRESENTATION.toStringOf(file)));
4157
}
4258
}

src/test/java/org/assertj/core/internal/FilesBaseTest.java

+4
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
import org.assertj.core.api.AssertionInfo;
3636
import org.assertj.core.util.diff.Delta;
3737
import org.junit.jupiter.api.BeforeEach;
38+
import org.junit.jupiter.api.io.TempDir;
3839

3940
/**
4041
* Base class for testing <code>{@link Files}</code>, set up diff and failures attributes (which is why it is in
@@ -46,6 +47,8 @@ public class FilesBaseTest {
4647

4748
protected static final AssertionInfo INFO = someInfo();
4849

50+
@TempDir
51+
protected File tempDir;
4952
protected File actual;
5053
protected Failures failures;
5154
protected Files files;
@@ -55,6 +58,7 @@ public class FilesBaseTest {
5558
protected BinaryDiff binaryDiff;
5659
protected NioFilesWrapper nioFilesWrapper;
5760

61+
@SuppressWarnings("unchecked")
5862
@BeforeEach
5963
public void setUp() {
6064
actual = mock(File.class);

0 commit comments

Comments
 (0)