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