001package io.ebean.test;
002
003import io.ebean.DB;
004
005import java.io.IOException;
006import java.io.InputStream;
007
008import static org.assertj.core.api.Assertions.assertThat;
009
010/**
011 * Helper for testing to assert that the JSON form of an entity
012 * or list of entities match a String / typically test resource.
013 *
014 * <pre>{@code
015 *
016 *    DbJson.of(timedEntries)
017 *      .replace("id", "eventTime")
018 *      .assertContentMatches("/assertJson/full-1-timed.json");
019 *
020 * }</pre>
021 */
022public class DbJson {
023
024  /**
025   * Create a PrettyJson object that has the JSON form of the
026   * entity bean or beans.
027   *
028   * <pre>{@code
029   *
030   *    DbJson.of(timedEntries)
031   *      .replace("id", "eventTime")
032   *      .assertContentMatches("/assertJson/full-1-timed.json");
033   *
034   * }</pre>
035   */
036  public static PrettyJson of(Object bean) {
037    return new PrettyJson(DB.json().toJsonPretty(bean));
038  }
039
040  /**
041   * Read the content for the given resource path.
042   */
043  public static String readResource(String resourcePath) {
044    InputStream is = DbJson.class.getResourceAsStream(resourcePath);
045    try {
046      return IOUtils.readUtf8(is).trim();
047    } catch (IOException e) {
048      throw new IllegalArgumentException(e);
049    }
050  }
051
052  /**
053   * Contains the JSON of beans(s).
054   */
055  public static class PrettyJson {
056
057    private String placeHolder = "\"*\"";
058    private String rawJson;
059
060    PrettyJson(String rawJson) {
061      this.rawJson = rawJson;
062    }
063
064    /**
065     * Set the placeHolder to use when replacing property values.
066     */
067    public PrettyJson withPlaceholder(String placeHolder) {
068      this.placeHolder = placeHolder;
069      return this;
070    }
071
072    /**
073     * Replace the values of the given properties with a placeholder value.
074     * <p>
075     * Typically we do this on generated properties such as id and timestamp properties.
076     * </p>
077     */
078    public PrettyJson replace(String... propertyNames) {
079      for (String propertyName : propertyNames) {
080        String placeholder = "\"" + propertyName + "\": " + placeHolder;
081        rawJson = rawJson.replaceAll("\"" + propertyName + "\": (\\d+)", placeholder);
082        rawJson = rawJson.replaceAll("\"" + propertyName + "\": \"(.*?)\"", placeholder);
083      }
084      return this;
085    }
086
087    /**
088     * Return the JSON content.
089     */
090    public String asJson() {
091      return rawJson;
092    }
093
094    /**
095     * Assert the json matches the content at the given resource path.
096     *
097     * <pre>{@code
098     *
099     *    DbJson.of(timedEntries)
100     *      .replace("id", "eventTime")
101     *      .assertContentMatches("/assertJson/full-1-timed.json");
102     *
103     * }</pre>
104     */
105    public void assertContentMatches(String resourcePath) {
106      assertThat(rawJson).isEqualTo(readResource(resourcePath));
107    }
108  }
109}