package com.bookshop.behavioral.templatemethod;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
import com.bookshop.domain.Book;
import java.math.BigDecimal;
import java.util.List;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
@DisplayName("Template Method -- one report skeleton, many output formats")
class SalesReportTest {
private final List<Book> sales = List.of(
new Book("978-0132350884", "Clean Code", "Robert C. Martin", new BigDecimal("32.50")),
new Book("978-0134685991", "Effective Java", "Joshua Bloch", new BigDecimal("39.99")));
@Test
@DisplayName("the CSV report fills the skeleton with CSV formatting")
void csvReport() {
String report = new CsvSalesReport().generate(sales);
assertEquals("""
title,author,price
Clean Code,Robert C. Martin,32.50
Effective Java,Joshua Bloch,39.99
total,,72.49
""", report);
}
@Test
@DisplayName("the HTML report reuses the identical skeleton and totalling logic")
void htmlReport() {
String report = new HtmlSalesReport().generate(sales);
assertTrue(report.startsWith("<table><tr><th>Title</th>"));
assertTrue(report.contains("<td>Clean Code</td>"));
assertTrue(report.endsWith("<tr><td>Total</td><td>72.49</td></tr></table>"));
}
@Test
@DisplayName("both formats agree on the total because the calculation exists exactly once")
void totalsCannotDrift() {
assertTrue(new CsvSalesReport().generate(sales).contains("72.49"));
assertTrue(new HtmlSalesReport().generate(sales).contains("72.49"));
}
}