Skip to content

Commit f020f04

Browse files
author
Fredrik Teschke
committed
✨ Add Snapshot.ignore(String... jsonPaths) method
1 parent 4de7788 commit f020f04

File tree

5 files changed

+150
-16
lines changed

5 files changed

+150
-16
lines changed

pom.xml

+6-1
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,11 @@
111111
<artifactId>slf4j-api</artifactId>
112112
<version>1.8.0-beta2</version>
113113
</dependency>
114+
<dependency>
115+
<groupId>com.jayway.jsonpath</groupId>
116+
<artifactId>json-path</artifactId>
117+
<version>2.4.0</version>
118+
</dependency>
114119
</dependencies>
115120

116121
<build>
@@ -224,4 +229,4 @@
224229
</plugin>
225230
</plugins>
226231
</build>
227-
</project>
232+
</project>

src/main/java/io/github/jsonSnapshot/Snapshot.java

+46-8
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,21 @@
11
package io.github.jsonSnapshot;
22

3+
import com.jayway.jsonpath.DocumentContext;
4+
import com.jayway.jsonpath.JsonPath;
5+
import com.jayway.jsonpath.spi.json.JacksonJsonProvider;
6+
import org.assertj.core.util.diff.DiffUtils;
7+
import org.assertj.core.util.diff.Patch;
8+
39
import java.lang.reflect.Method;
10+
import java.util.ArrayList;
411
import java.util.Arrays;
512
import java.util.Collection;
13+
import java.util.List;
614
import java.util.Set;
715
import java.util.function.Function;
16+
import java.util.stream.Collectors;
817

9-
import org.assertj.core.util.diff.DiffUtils;
10-
import org.assertj.core.util.diff.Patch;
18+
import static io.github.jsonSnapshot.SnapshotMatcher.defaultJsonFunction;
1119

1220
public class Snapshot {
1321

@@ -19,6 +27,8 @@ public class Snapshot {
1927

2028
private Function<Object, String> jsonFunction;
2129

30+
private final List<String> pathsToIgnore = new ArrayList<>();
31+
2232
private Object[] current;
2333

2434
Snapshot(
@@ -65,11 +75,11 @@ private SnapshotMatchException generateDiffError(String rawSnapshot, String curr
6575
+ currentObject.trim()
6676
+ "\n\n"
6777
+ patch
68-
.getDeltas()
69-
.stream()
70-
.map(delta -> delta.toString() + "\n")
71-
.reduce(String::concat)
72-
.get();
78+
.getDeltas()
79+
.stream()
80+
.map(delta -> delta.toString() + "\n")
81+
.reduce(String::concat)
82+
.get();
7383
return new SnapshotMatchException(error);
7484
}
7585

@@ -83,11 +93,39 @@ private String getRawSnapshot(Collection<String> rawSnapshots) {
8393
return null;
8494
}
8595

96+
private Object ignorePaths(Object input) {
97+
DocumentContext context = JsonPath.using(new JacksonJsonProvider()).parse(defaultJsonFunction().apply(input));
98+
this.pathsToIgnore.forEach(path -> context.delete(path));
99+
String root = "$";
100+
return context.read(root);
101+
}
102+
103+
private Object[] getCurrentWithoutIgnoredPaths() {
104+
if (pathsToIgnore.isEmpty() || current == null) {
105+
return current;
106+
}
107+
108+
return Arrays.asList(current).stream()
109+
.map(this::ignorePaths)
110+
.collect(Collectors.toList())
111+
.toArray();
112+
}
113+
86114
private String takeSnapshot() {
87-
return getSnapshotName() + jsonFunction.apply(current);
115+
return getSnapshotName() + jsonFunction.apply(getCurrentWithoutIgnoredPaths());
88116
}
89117

90118
public String getSnapshotName() {
91119
return clazz.getName() + "." + method.getName() + "=";
92120
}
121+
122+
/**
123+
* Ignore fields when comparing object and snapshot.
124+
*
125+
* @param jsonPathsToIgnore A list of paths to ignore in <a href="https://github.com/json-path/JsonPath">JsonPath</a> syntax.
126+
*/
127+
public Snapshot ignoring(String... jsonPathsToIgnore) {
128+
this.pathsToIgnore.addAll(Arrays.asList(jsonPathsToIgnore));
129+
return this;
130+
}
93131
}

src/test/java/io/github/jsonSnapshot/SnapshotIntegrationTest.java

+24
Original file line numberDiff line numberDiff line change
@@ -73,4 +73,28 @@ void shouldThrowStackOverflowError() {
7373

7474
assertThrows(SnapshotMatchException.class, () -> expect(fakeObject1).toMatchSnapshot());
7575
}
76+
77+
@Test
78+
public void shouldMatchSnapshotAndIgnoreTopLevelFieldMethod() {
79+
expect(FakeObject.builder().id("anyId6").value(6).name("anyName6").build())
80+
.ignoring("value")
81+
.toMatchSnapshot();
82+
}
83+
84+
@Test
85+
public void shouldMatchSnapshotAndIgnoreSeveralNestedFieldsMethod() {
86+
FakeObject grandChild = FakeObject.builder().id("grandChild7").value(7).build();
87+
FakeObject child = FakeObject.builder().id("child7").value(7).fakeObject(grandChild).build();
88+
expect(FakeObject.builder().id("anyId7").value(7).name("anyName7").fakeObject(child).build())
89+
.ignoring("value", "fakeObject.id", "fakeObject.fakeObject")
90+
.toMatchSnapshot();
91+
}
92+
93+
@Test
94+
public void shouldMatchSnapshotAndIgnoreEverythingMethod() {
95+
FakeObject child = FakeObject.builder().id("child8").value(8).build();
96+
expect(FakeObject.builder().id("anyId8").value(8).name("anyName8").fakeObject(child).build())
97+
.ignoring("$..*")
98+
.toMatchSnapshot();
99+
}
76100
}

src/test/java/io/github/jsonSnapshot/SnapshotIntegrationTest.snap

+24
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,27 @@
1+
io.github.jsonSnapshot.SnapshotIntegrationTest.shouldMatchSnapshotAndIgnoreEverythingMethod=[
2+
{ }
3+
]
4+
5+
6+
io.github.jsonSnapshot.SnapshotIntegrationTest.shouldMatchSnapshotAndIgnoreSeveralNestedFieldsMethod=[
7+
{
8+
"fakeObject": {
9+
"value": 7
10+
},
11+
"id": "anyId7",
12+
"name": "anyName7"
13+
}
14+
]
15+
16+
17+
io.github.jsonSnapshot.SnapshotIntegrationTest.shouldMatchSnapshotAndIgnoreTopLevelFieldMethod=[
18+
{
19+
"id": "anyId6",
20+
"name": "anyName6"
21+
}
22+
]
23+
24+
125
io.github.jsonSnapshot.SnapshotIntegrationTest.shouldMatchSnapshotFour=[
226
{
327
"id": "anyId4",

src/test/java/io/github/jsonSnapshot/SnapshotTest.java

+50-7
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,15 @@
66
import java.io.IOException;
77
import java.nio.file.Files;
88
import java.nio.file.Paths;
9+
import java.util.Collections;
910
import java.util.TreeSet;
1011
import java.util.stream.Collectors;
1112
import java.util.stream.Stream;
1213

14+
import com.fasterxml.jackson.core.JsonParser;
15+
import com.fasterxml.jackson.databind.ObjectMapper;
16+
import com.jayway.jsonpath.PathNotFoundException;
17+
import org.junit.Before;
1318
import org.junit.jupiter.api.AfterEach;
1419
import org.junit.jupiter.api.BeforeEach;
1520
import org.junit.jupiter.api.Test;
@@ -31,20 +36,23 @@ class SnapshotTest {
3136
@BeforeEach
3237
void setUp() throws NoSuchMethodException, IOException {
3338
snapshotFile = new SnapshotFile(DEFAULT_CONFIG.getFilePath(), "anyFilePath");
34-
snapshot =
35-
new Snapshot(
36-
snapshotFile,
37-
String.class,
38-
String.class.getDeclaredMethod("toString"),
39-
SnapshotMatcher.defaultJsonFunction(),
40-
"anyObject");
39+
snapshot = createSnapshot("anyObject");
4140
}
4241

4342
@AfterEach
4443
void tearDown() throws IOException {
4544
Files.delete(Paths.get(FILE_PATH));
4645
}
4746

47+
private Snapshot createSnapshot(Object... current) throws NoSuchMethodException {
48+
return new Snapshot(
49+
snapshotFile,
50+
String.class,
51+
String.class.getDeclaredMethod("toString"),
52+
SnapshotMatcher.defaultJsonFunction(),
53+
current);
54+
}
55+
4856
@Test
4957
void shouldGetSnapshotNameSuccessfully() {
5058
String snapshotName = snapshot.getSnapshotName();
@@ -64,4 +72,39 @@ void shouldMatchSnapshotWithException() {
6472

6573
assertThrows(SnapshotMatchException.class, snapshot::toMatchSnapshot);
6674
}
75+
76+
@Test
77+
public void shouldNotFailOnEmptyIgnoredPathList() {
78+
snapshot.ignoring().toMatchSnapshot();
79+
assertThat(snapshotFile.getRawSnapshots()).isEqualTo(Stream.of(SNAPSHOT).collect(Collectors.toCollection(TreeSet::new)));
80+
}
81+
82+
@Test
83+
public void shouldFailWhenTryingToIgnoreChildOfPrimitiveJsonObject() {
84+
assertThrows(PathNotFoundException.class, () -> snapshot.ignoring("anyObject_is_a_json_string_and_can_not_have_children").toMatchSnapshot());
85+
}
86+
87+
@Test
88+
public void shouldIgnoreTopLevelAndNestedFields() throws NoSuchMethodException, IOException {
89+
Object object = new ObjectMapper().readTree("{\n" +
90+
" \"notIgnored\": \"notIgnored\",\n" +
91+
" \"ignoredInParent\": \"ignored\",\n" +
92+
" \"child\": {\n" +
93+
" \"ignoredInParent\": \"notIgnored\",\n" +
94+
" \"ignoredInChild\": \"ignored\"\n" +
95+
" }\n" +
96+
"}");
97+
Snapshot snapshot = createSnapshot(object);
98+
99+
snapshot.ignoring("ignoredInParent", "child.ignoredInChild").toMatchSnapshot();
100+
String expectedSnapshot = "java.lang.String.toString=[\n" +
101+
" {\n" +
102+
" \"child\": {\n" +
103+
" \"ignoredInParent\": \"notIgnored\"\n" +
104+
" },\n" +
105+
" \"notIgnored\": \"notIgnored\"\n" +
106+
" }\n" +
107+
"]";
108+
assertThat(snapshotFile.getRawSnapshots()).isEqualTo(Collections.singleton(expectedSnapshot));
109+
}
67110
}

0 commit comments

Comments
 (0)