package example.helloworld;

import org.teleal.common.xhtml.XHTML;
import example.util.DocletTest;
import org.testng.annotations.Test;

import static org.testng.Assert.assertEquals;

/**
 * Hello World: Creating testable documentation
 * <p>
 * Let's assume you want to test <em>and</em> document the following {@code HelloWorld} Java class:
 * </p>
 * <a class="citation" href="javacode://example.helloworld.HelloWorld">Citation</a>
 * <p>
 * First, write a unit test method that checks the class:
 * </p>
 * <a class="citation" href="javacode://example.helloworld.HelloWorldTest#testHelloWorld()">Citation</a>
 * <p>
 * This unit test not only validates the correct behavior of the class, it also shows how the class is
 * supposed to be used. Traditionally, you'd now add a section in your software's manual, where you copy and
 * paste the code of the {@code HelloWorld} class and some lines from the unit test. Your users will
 * then be able to understand the internals and how they should work with the class.
 * </p>
 * <p>
 * With Lemma you don't copy/paste anything but write documentation as Javadoc on the test method in XHTML syntax:
 * </p>
 * <a class="citation" href="javacode://example.helloworld.HelloWorldTest" style="include: TEST_HELLOWORLD; clean-labels: boundary;">Citation</a>
 * <p>
 * You probably already know all of the XHTML elements and attributes used in this Javadoc comment, in fact, you can
 * use any tags you need to write your documentation.
 * </p>
 * <p>
 * Lemma parses your markup and replaces the content of
 * {@code <a>} elements that have a {@code citation} class. The first anchor in the example above is
 * referencing the raw Java source code of a class called {@code example.helloworld.HelloWorld}. How this source
 * code is found by Lemma depends on your configuration, we'll look at that later. Note how the URL scheme
 * {@code javacode://} is used to indicate what part of the referenced resource you want to cite. This URL is actually
 * refactoring-safe, your IDE should be able to automatically update the URL string when you rename the package or
 * {@code HelloWorld} class name.
 * </p>
 * <p>
 * The second anchor is more specific, it's a citation for a fragment of code. The URL references the source of the
 * test class and the test method (yes, it's referencing "itself"). You'll probably recognize the method reference syntax
 * from Javadoc, it's the same as for regular Javadoc {@code @link} and {@code @see} tags, hence also safe for
 * refactoring. Citation options are declared with the {@code style} attribute, they look like CSS options. The
 * {@code include} option shown here accepts a list of fragment labels which should be cited. A fragment label is
 * a Java line comment starting with "{@code // DOC: (LABEL)}". Two lines with the same label mark the beginning and end
 * of a fragment block. So this citation will only include the four lines of the method body. You'll later see more
 * details about citation options, fragments, and labels.
 * </p>
 * <p>
 * The previous Javadoc represents just one small section of your overall documentation. Lemma's default processing
 * pipeline expects that you also create a master template file in XHTML that brings together all of your documentation
 * parts, chapters, and sections. How that template looks like, and how parts, chapters, and sections are organized and
 * finally rendered is up to you. Here is a simple example of a template:
 * </p>
 * <a class="citation" href="example/helloworld/example01_input.xhtml">Citation</a>
 * <p>
 * Note that the URL scheme for this citation is {@code javadoc://}. The Lemma processor will follow the URL
 * to your test class and test method, and then read and process the Javadoc comment of that resource. This is a recursive
 * procedure, so any citation anchors in the Javadoc comment are followed and processed as well. Finally, the following output
 * is generated:
 * </p>
 * <a class="citation" href="example/helloworld/example01_output.xhtml">Citation</a>
 * <p>
 * The formatting and indentation of this XHTML document has been automatically generated by a pretty printer, so it
 * readability could obvioulsy be improved. All Javadoc code fragments have been properly escaped in CDATA sections. All
 * cited source fragments have been escaped with XHTML entities instead (future versions of Lemma will likely embed
 * XHTML markup for callouts into code blocks, hence they are not defined as CDATA sections).
 * </p>
 * <p>
 * This is how it looks rendered in a browser:
 * </p>
 * <img src="doc-files/helloworld_rendered_output.png" style="border: 1px solid black;" alt="HelloWorld Output"/>
 */
public class HelloWorldTest extends DocletTest {

    // DOC: TEST_HELLOWORLD
    /**
     * The {@code HelloWorld} class
     * <p>
     * This is the source of the class:
     * </p>
     *
     * <a class="citation"
          href="javacode://example.helloworld.HelloWorld"/>
     *
     * <p>
     * To use the class, first instantiate it, then call either {@code getMessage()} to retrieve
     * the message string or {@code sayHello()} to print the message to {@code System.out}:
     * </p>
     *
     * <a class="citation"
          href="javacode://example.helloworld.HelloWorldTest#testHelloWorld()"
          style="include: HELLOWORLD_USAGE;"/>
     *
     * <p>
     * If you don't want the message printed to {@code System.out}, don't call the
     * {@code sayHello()} method.
     * </p>
     */
    @Test
    public void testHelloWorld() {
        HelloWorld hw = new HelloWorld();                   // DOC: HELLOWORLD_USAGE
        assert hw.getMessage().equals("Hello World!");
        assert hw.getMessage().endsWith("!");
        hw.sayHello();                                      // DOC: HELLOWORLD_USAGE
    }
    // DOC: TEST_HELLOWORLD

    @Test
    public void processDocumentation() throws Exception {
        XHTML output = getTemplatePipeline().execute(
                parseDocument("example/helloworld/example01_input.xhtml")
        );

        assertEquals(
                getParser().print(output),
                getContent("example/helloworld/example01_output.xhtml")
        );
    }
}
