| /* |
| * Copyright 2020 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package com.google.devsite.components.impl |
| |
| import com.google.common.truth.Truth.assertThat |
| import com.google.devsite.components.DescriptionComponent.Params |
| import com.google.devsite.testing.ConverterTestBase |
| import kotlinx.html.body |
| import kotlinx.html.stream.createHTML |
| import org.jetbrains.dokka.model.DModule |
| import org.jetbrains.dokka.model.Documentable |
| import org.junit.Test |
| |
| internal class DefaultDescriptionComponentTest : ConverterTestBase() { |
| @Test |
| fun `Single sentence renders correctly`() { |
| val component = """ |
| |/** Hello world! */ |
| |class Foo |
| """.render().description() |
| |
| val output = createHTML().body { |
| component.render(this) |
| }.trim() |
| |
| // language=html |
| assertThat(output).isEqualTo( |
| """ |
| <body> |
| <p>Hello world!</p> |
| </body> |
| """.trim() |
| ) |
| } |
| |
| @Test |
| fun `Deprecation renders renders correctly`() { |
| val component = """ |
| |/** Hello world! */ |
| |class Foo |
| """.render().description( |
| deprecation = "This class is deprecated." |
| ) |
| |
| val output = createHTML().body { |
| component.render(this) |
| }.trim() |
| |
| // language=html |
| assertThat(output).isEqualTo( |
| """ |
| <body> |
| <aside class="caution"><strong>This class is deprecated.</strong><br> |
| <p>Hello world!</p> |
| </aside> |
| </body> |
| """.trim() |
| ) |
| } |
| |
| @Test |
| fun `Summary trims documentation on period`() { |
| val component = """ |
| |/** |
| | * 1 2 3. 4 5 6 |
| | * |
| | * Stuff. |
| | */ |
| |class Foo |
| """.render().description(summary = true) |
| |
| val output = createHTML().body { |
| component.render(this) |
| }.trim() |
| |
| // language=html |
| assertThat(output).isEqualTo( |
| """ |
| <body> |
| <p>1 2 3.</p> |
| </body> |
| """.trim() |
| ) |
| } |
| |
| @Test |
| fun `Summary ignores period in word`() { |
| val component = """ |
| |/** |
| | * This is foo.bar, blah blah. |
| | * |
| | * Stuff. |
| | */ |
| |class Foo |
| """.render().description(summary = true) |
| |
| val output = createHTML().body { |
| component.render(this) |
| }.trim() |
| |
| // language=html |
| assertThat(output).isEqualTo( |
| """ |
| <body> |
| <p>This is foo.bar, blah blah.</p> |
| </body> |
| """.trim() |
| ) |
| } |
| |
| @Test |
| fun `Summary ignores period in link`() { |
| val component = """ |
| |/** [Foo.Bar] has great drinks. */ |
| |class Foo |
| """.render().description(summary = true) |
| |
| val output = createHTML().body { |
| component.render(this) |
| }.trim() |
| |
| // language=html |
| assertThat(output).isEqualTo( |
| """ |
| <body> |
| <p>Foo.Bar has great drinks.</p> |
| </body> |
| """.trim() |
| ) |
| } |
| |
| @Test |
| fun `Summary breaks on period space code tag`() { |
| val component1 = """ |
| |/** |
| | * This is a complete sentence. <code>Foo.hashCode</code> is a function. |
| | */ |
| |class Foo |
| """.render().description(summary = true) |
| val component2 = """ |
| |/** |
| | * This is a complete sentence. |
| | * <code>Foo.hashCode</code> is a function. |
| | */ |
| |class Foo |
| """.render().description(summary = true) |
| |
| val output1 = createHTML().body { |
| component1.render(this) |
| }.trim() |
| val output2 = createHTML().body { |
| component2.render(this) |
| }.trim() |
| val expected = """ |
| <body> |
| <p>This is a complete sentence.</p> |
| </body> |
| """.trim() |
| // language=html |
| assertThat(output1).isEqualTo(expected) |
| assertThat(output2).isEqualTo(expected) |
| } |
| |
| @Test |
| fun `Summary breaks on period space markdown-code`() { |
| val component = """ |
| |/** |
| | * This [Animatable] function creates a float value holder that automatically |
| | * animates its value when the value is changed via [animateTo]. [Animatable] supports value |
| | * change during an ongoing value change animation. |
| | */ |
| |class Foo |
| """.render().description(summary = true) |
| |
| val output = createHTML().body { |
| component.render(this) |
| }.trim() |
| |
| // language=html |
| assertThat(output).isEqualTo( |
| """ |
| <body> |
| <p>This Animatable function creates a float value holder that automatically animates its value when the value is changed via animateTo.</p> |
| </body> |
| """.trim() |
| ) |
| } |
| |
| @Test |
| fun `Summary breaks on new paragraph even without ending period`() { |
| val component = """ |
| |/** |
| | * Animation will be forced to end when its value reaches upper/lower bound (if they have |
| | * been defined, e.g. via [Animatable.updateBounds]) |
| | * |
| | * Unlike [Finished], when an animation ends due to [BoundReached], it often falls short |
| | * from its initial target, and the remaining velocity is often non-zero. Both the end value |
| | * and the remaining velocity can be obtained via [AnimationResult]. |
| | */ |
| |class Foo |
| """.render().description(summary = true) |
| |
| val output = createHTML().body { |
| component.render(this) |
| }.trim() |
| |
| // language=html |
| assertThat(output).isEqualTo( |
| """ |
| <body> |
| <p>Animation will be forced to end when its value reaches upper/lower bound (if they have been defined, e.g. via Animatable.updateBounds)</p> |
| </body> |
| """.trim() |
| ) |
| } |
| |
| @Test |
| fun `Spacing does not confuse sentence-end detector`() { |
| val component = """ |
| |/** |
| | * the amount of time (in milliseconds) the animation will take to finish. |
| | * Defaults to [DefaultDuration] |
| | */ |
| |class Foo |
| """.render().description(summary = true) |
| |
| val output = createHTML().body { |
| component.render(this) |
| }.trim() |
| |
| // language=html |
| assertThat(output).isEqualTo( |
| """ |
| <body> |
| <p>the amount of time (in milliseconds) the animation will take to finish.</p> |
| </body> |
| """.trim() |
| ) |
| } |
| |
| @Test |
| fun `Deprecation summary renders renders correctly`() { |
| val component = """ |
| |/** |
| | * Hello world! |
| | */ |
| |class Foo |
| """.render().description( |
| summary = true, |
| deprecation = "This class is deprecated." |
| ) |
| |
| val output = createHTML().body { |
| component.render(this) |
| }.trim() |
| // TODO(b/171570474) Work around for EOL space introduced by Dokka and is required to make the |
| // test pass but, stripped by the IDE |
| // language=html |
| assertThat(output).isEqualTo( |
| "<body>\n" + |
| " <p><strong>This class is deprecated.</strong>\n" + |
| " <p>Hello world!</p>\n" + |
| " </p>\n" + |
| " </body>".trim() |
| ) |
| } |
| |
| @Test |
| fun `Paragraphs render correctly`() { |
| val component = """ |
| |/** |
| | * There was an old lady who swallowed a fly. |
| | * I dunno why she swallowed that fly, |
| | * Perhaps she'll die. |
| | * |
| | * ... |
| | * |
| | * There was an old lady who swallowed a cow. |
| | * I don't know how she swallowed a cow! |
| | * She swallowed the cow to catch the goat... |
| | * She swallowed the goat to catch the dog... |
| | * She swallowed the dog to catch the cat... |
| | * She swallowed the cat to catch the bird ... |
| | * She swallowed the bird to catch the spider |
| | * That wiggled and wiggled and tickled inside her. |
| | * She swallowed the spider to catch the fly. |
| | * But I dunno why she swallowed that fly |
| | * Perhaps she'll die. |
| | * |
| | * There was an old lady who swallowed a horse - |
| | * She's dead, of course. |
| | */ |
| |class Foo |
| """.render().description() |
| |
| val output = createHTML().body { |
| component.render(this) |
| }.trim() |
| |
| // language=html |
| assertThat(output).isEqualTo( |
| """ |
| <body> |
| <p>There was an old lady who swallowed a fly. I dunno why she swallowed that fly, Perhaps she'll die.</p> |
| <p>...</p> |
| <p>There was an old lady who swallowed a cow. I don't know how she swallowed a cow! She swallowed the cow to catch the goat... She swallowed the goat to catch the dog... She swallowed the dog to catch the cat... She swallowed the cat to catch the bird ... She swallowed the bird to catch the spider That wiggled and wiggled and tickled inside her. She swallowed the spider to catch the fly. But I dunno why she swallowed that fly Perhaps she'll die.</p> |
| <p>There was an old lady who swallowed a horse - She's dead, of course.</p> |
| </body> |
| """.trim() |
| ) |
| } |
| |
| @Test |
| fun `Line breaks render correctly`() { |
| val component = """ |
| |/** |
| | * A \ |
| | * B \ |
| | * C. |
| | */ |
| |class Foo |
| """.render().description() |
| |
| val output = createHTML().body { |
| component.render(this) |
| }.trim() |
| |
| // language=html |
| assertThat(output).isEqualTo( |
| """ |
| <body> |
| <p>A <br>B <br>C.</p> |
| </body> |
| """.trim() |
| ) |
| } |
| |
| @Test |
| fun `Inline code renders correctly in 4x Kotlin and Java`() { |
| val componentK = """ |
| |/** The `Boolean` type has two possible values: `true` or `false`. */ |
| |class Foo |
| """.render().description() |
| val componentJ = """ |
| |/** The {@code Boolean} type has two possible values: {@code true} or {@code false}. */ |
| |public class Foo |
| """.render(java = true).description() |
| |
| for (component in listOf(componentJ, componentK)) { |
| val output = createHTML().body { |
| component.render(this) |
| }.trim() |
| |
| // language=html |
| assertThat(output).isEqualTo( |
| """ |
| <body> |
| <p>The <code>Boolean</code> type has two possible values: <code>true</code> or <code>false</code>.</p> |
| </body> |
| """.trim() |
| ) |
| } |
| } |
| |
| @Test |
| fun `Formatted text renders correctly`() { |
| val component = """ |
| |/** *Italics*, **Bold**, ***Both***, ~~Bad~~. */ |
| |class Foo |
| """.render().description() |
| |
| val output = createHTML(prettyPrint = false).body { |
| component.render(this) |
| }.trim() |
| |
| // language=html |
| assertThat(output).isEqualTo( |
| """ |
| <body><p><em>Italics</em>, <b>Bold</b>, <em><b>Both</b></em>, <del>Bad</del>.</p></body> |
| """.trim() |
| ) |
| } |
| |
| @Test |
| fun `Itemized list renders correctly`() { |
| val component = """ |
| |/** |
| | * Stuff: |
| | * - Thing 1 |
| | * - Thing 2 |
| | * - Thing 3 |
| | */ |
| |class Foo |
| """.render().description() |
| |
| val output = createHTML().body { |
| component.render(this) |
| }.trim() |
| |
| // language=html |
| assertThat(output).isEqualTo( |
| """ |
| <body> |
| <p>Stuff:</p> |
| <ul> |
| <li> |
| <p>Thing 1</p> |
| </li> |
| <li> |
| <p>Thing 2</p> |
| </li> |
| <li> |
| <p>Thing 3</p> |
| </li> |
| </ul> |
| </body> |
| """.trim() |
| ) |
| } |
| |
| @Test |
| fun `Numbered list renders correctly`() { |
| val component = """ |
| |/** |
| | * Stuff: |
| | * 1. Thing 1 |
| | * 2. Thing 2 |
| | * 3. Thing 3 |
| | */ |
| |class Foo |
| """.render().description() |
| |
| val output = createHTML().body { |
| component.render(this) |
| }.trim() |
| |
| // language=html |
| assertThat(output).isEqualTo( |
| """ |
| <body> |
| <p>Stuff:</p> |
| <ol> |
| <li> |
| <p>Thing 1</p> |
| </li> |
| <li> |
| <p>Thing 2</p> |
| </li> |
| <li> |
| <p>Thing 3</p> |
| </li> |
| </ol> |
| </body> |
| """.trim() |
| ) |
| } |
| |
| @Test |
| fun `Numbered list renders correctly from html`() { |
| val component = """ |
| |/** |
| | * <ol> |
| | * <li> |
| | * <p>Thing 1</p> |
| | * </li> |
| | * <li> |
| | * <p>Thing 2</p> |
| | * </li> |
| | * <li> |
| | * <p>Thing 3</p> |
| | * </li> |
| | * </ol> |
| | */ |
| |public class Foo {} |
| """.render(java = true).description() |
| |
| val output = createHTML().body { |
| component.render(this) |
| }.trim() |
| |
| // language=html |
| assertThat(output).isEqualTo( |
| """ |
| <body> |
| <ol> |
| <li> |
| <p>Thing 1</p> |
| </li> |
| <li> |
| <p>Thing 2</p> |
| </li> |
| <li> |
| <p>Thing 3</p> |
| </li> |
| </ol> |
| </body> |
| """.trim() |
| ) |
| } |
| |
| // TODO fix handling @link inside dt, dd b/217937742 |
| @Test |
| fun `Description list renders correctly in kotlin`() { |
| val component = """ |
| |/** |
| | * <dl> |
| | * <dt> |
| | * <code>name="<i>name</i>"</code> |
| | * </dt> |
| | * <dd> |
| | * A URI path segment. |
| | * </dd> |
| | * <dt> |
| | * An {@link Intent} to navigate. |
| | * </dt> |
| | * <dd> |
| | * The subdirectory you're sharing. |
| | * </dd> |
| | * </dl> |
| | */ |
| |public class Foo {} |
| """.render().description() |
| |
| val output = createHTML().body { |
| component.render(this) |
| }.trim() |
| |
| // language=html |
| assertThat(output).isEqualTo( |
| """ |
| <body><dl> |
| <dt> |
| <code>name="<i>name</i>"</code> |
| </dt> |
| <dd> |
| A URI path segment. |
| </dd> |
| <dt> |
| An {@link Intent} to navigate. |
| </dt> |
| <dd> |
| The subdirectory you're sharing. |
| </dd> |
| </dl></body> |
| """.trim() |
| ) |
| } |
| |
| // TODO fix handling @link inside dt, dd b/217937742 |
| // TODO remove improper handling of dt that requires <p> b/217941159 |
| @Test |
| fun `Description list renders correctly in java`() { |
| val component = """ |
| |/** |
| | * <dl> |
| | * <dt> |
| | * <code>name="<i>name</i>"</code> |
| | * </dt> |
| | * <dd> |
| | * A URI path segment. |
| | * </dd> |
| | * <dt> |
| | * An {@link Intent} to navigate |
| | * </dt> |
| | * <dd> |
| | * The subdirectory you're sharing. |
| | * </dd> |
| | * </dl> |
| | */ |
| |public class Foo {} |
| """.render(java = true).description() |
| |
| val output = createHTML().body { |
| component.render(this) |
| }.trim() |
| |
| // language=html |
| assertThat(output).isEqualTo( |
| """ |
| <body> |
| <dl> |
| <dt><p><code>name="<em>name</em>"</code></p> |
| </dt> |
| <dd> A URI path segment. </dd> |
| <dt><p> An Intent to navigate </p> |
| </dt> |
| <dd> The subdirectory you're sharing. </dd> |
| </dl> |
| </body> |
| """.trim() |
| ) |
| } |
| |
| @Test |
| fun `Nested lists render correctly`() { |
| val component = """ |
| |/** |
| | * Stuff: |
| | * * a |
| | * 1. a |
| | * 2. b |
| | * 3. c |
| | * * b |
| | * - a |
| | * - b |
| | * - c |
| | * * a |
| | * * c |
| | */ |
| |class Foo |
| """.render().description() |
| |
| val output = createHTML().body { |
| component.render(this) |
| }.trim() |
| |
| // language=html |
| assertThat(output).isEqualTo( |
| """ |
| <body> |
| <p>Stuff:</p> |
| <ul> |
| <li> |
| <p>a</p> |
| </li> |
| <ol> |
| <li> |
| <p>a</p> |
| </li> |
| <li> |
| <p>b</p> |
| </li> |
| <li> |
| <p>c</p> |
| </li> |
| </ol> |
| <li> |
| <p>b</p> |
| </li> |
| <ul> |
| <li> |
| <p>a</p> |
| </li> |
| <li> |
| <p>b</p> |
| </li> |
| <li> |
| <p>c</p> |
| </li> |
| <ul> |
| <li> |
| <p>a</p> |
| </li> |
| </ul> |
| </ul> |
| <li> |
| <p>c</p> |
| </li> |
| </ul> |
| </body> |
| """.trim() |
| ) |
| } |
| |
| @Test |
| fun `Table renders correctly`() { |
| val component = """ |
| |/** |
| | * | Tables | Are | Cool | |
| | * |----------|:-------------:|-----------:| |
| | * | col 1 is | left-aligned | ${'$'}1600 | |
| | * | col 2 is | centered | ${'$'}12 | |
| | * | col 3 is | right-aligned | ${'$'}1 | |
| | */ |
| |class Foo |
| """.render().description() |
| |
| val output = createHTML().body { |
| component.render(this) |
| }.trim() |
| |
| // language=html |
| assertThat(output).isEqualTo( |
| """ |
| <body> |
| <table> |
| <tr> |
| <td>Tables</td> |
| <td>Are</td> |
| <td>Cool</td> |
| </tr> |
| <tr> |
| <td>col 1 is</td> |
| <td>left-aligned</td> |
| <td>${'$'}1600</td> |
| </tr> |
| <tr> |
| <td>col 2 is</td> |
| <td>centered</td> |
| <td>${'$'}12</td> |
| </tr> |
| <tr> |
| <td>col 3 is</td> |
| <td>right-aligned</td> |
| <td>${'$'}1</td> |
| </tr> |
| </table> |
| </body> |
| """.trim() |
| ) |
| } |
| |
| @Test |
| fun `Code blocks render correctly`() { |
| val component = """ |
| |/** |
| | * Welcome: |
| | * |
| | * ```kotlin |
| | * fun main() { |
| | * println("Hello World!") |
| | * } |
| | * ``` |
| | * |
| | * fun thisIsACodeBlock() { |
| | * val butWhy = "per markdown spec, because four-spaces prefix" |
| | * } |
| | */ |
| |class Foo |
| """.render().description() |
| |
| val output = createHTML().body { |
| component.render(this) |
| }.trim() |
| |
| // language=html |
| assertThat(output).isEqualTo( |
| """ |
| <body> |
| <p>Welcome:</p> |
| <pre class="prettyprint">fun main() {<br> println("Hello World!")<br>}</pre> |
| <pre class="prettyprint"> fun thisIsACodeBlock() { |
| val butWhy = "per markdown spec, because four-spaces prefix" |
| }</pre> |
| </body> |
| """.trim() |
| ) |
| } |
| |
| @Test |
| fun `Plain link renders correctly`() { |
| val component = """ |
| |/** Click [here](http://meme). */ |
| |class Foo |
| """.render().description() |
| |
| val output = createHTML().body { |
| component.render(this) |
| }.trim() |
| |
| // language=html |
| assertThat(output).isEqualTo( |
| """ |
| <body> |
| <p>Click <a href="http://meme">here</a>.</p> |
| </body> |
| """.trim() |
| ) |
| } |
| |
| @Test |
| fun `Link to type renders correctly`() { |
| val component = """ |
| |class Bar |
| | |
| |/** [Bar] is pretty cool. */ |
| |class Foo |
| """.render().description() |
| |
| val output = createHTML().body { |
| component.render(this) |
| }.trim() |
| |
| // language=html |
| assertThat(output).isEqualTo( |
| """ |
| <body> |
| <p><code><a href="/reference/androidx/example/Bar.html">Bar</a></code> is pretty cool.</p> |
| </body> |
| """.trim() |
| ) |
| } |
| |
| @Test |
| fun `Link to symbol renders correctly`() { |
| val component = """ |
| |fun bar() = Unit |
| | |
| |/** [bar] is pretty cool. */ |
| |class Foo |
| """.render().description() |
| |
| val output = createHTML().body { |
| component.render(this) |
| }.trim() |
| |
| // language=html |
| assertThat(output).isEqualTo( |
| """ |
| <body> |
| <p><code><a href="/reference/androidx/example/package-summary.html#bar()">bar</a></code> is pretty cool.</p> |
| </body> |
| """.trim() |
| ) |
| } |
| |
| @Test |
| fun `Named link to type renders correctly`() { |
| val component = """ |
| |class BarIsVeryVeryVeryVeryLongNamed |
| | |
| |/** [Special snowflake snowflake snowflake snowflake snowflake][BarIsVeryVeryVeryVeryLongNamed] |
| | * is pretty cool. |
| | */ |
| |class Foo |
| """.render().description() |
| |
| val output = createHTML().body { |
| component.render(this) |
| }.trim() |
| |
| // language=html |
| assertThat(output).isEqualTo( |
| """ |
| <body> |
| <p><code><a href="/reference/androidx/example/BarIsVeryVeryVeryVeryLongNamed.html">Special snowflake snowflake snowflake snowflake snowflake</a></code> is pretty cool.</p> |
| </body> |
| """.trim() |
| ) |
| } |
| |
| @Test |
| fun `Image renders correctly`() { |
| val component = """ |
| |/** ![Alt text](/path/to/img.jpg "Image Title") */ |
| |class Foo |
| """.render().description() |
| |
| val output = createHTML().body { |
| component.render(this) |
| }.trim() |
| |
| // language=html |
| assertThat(output).isEqualTo( |
| """ |
| <body> |
| <p><img alt="Alt text" src="/path/to/img.jpg"></p> |
| </body> |
| """.trim() |
| ) |
| } |
| |
| @Test |
| fun `Quote renders correctly`() { |
| val component = """ |
| |/** |
| | * > Two things are infinite: the universe and human stupidity; and I'm not sure about |
| | * > the universe. -- Albert Einstein |
| | */ |
| |class Foo |
| """.render().description() |
| |
| val output = createHTML().body { |
| component.render(this) |
| }.trim() |
| |
| // language=html |
| assertThat(output).isEqualTo( |
| """ |
| <body> |
| <blockquote> |
| <p>Two things are infinite: the universe and human stupidity; and I'm not sure about the universe. -- Albert Einstein</p> |
| </blockquote> |
| </body> |
| """.trim() |
| ) |
| } |
| |
| @Test |
| fun `Strikethrough renders correctly`() { |
| val component = """ |
| |/** ~~Hello~~ world! */ |
| |class Foo |
| """.render().description() |
| |
| val output = createHTML().body { |
| component.render(this) |
| }.trim() |
| |
| // language=html |
| assertThat(output).isEqualTo( |
| """ |
| <body> |
| <p> |
| <del>Hello</del> |
| world!</p> |
| </body> |
| """.trim() |
| ) |
| } |
| |
| @Test |
| fun `Pre and @code handled correctly`() { |
| val component = """ |
| |/** |
| | * {@code |
| | * fun thisIsANonPreCodeBlock() { |
| | * doNotPreserveWhitespace: String \\ blah |
| | * } |
| | * } |
| | * <pre>{@code |
| | * fun thisIsAPreCodeBlock() { |
| | * DOPreserveWhitespace: String \\ blah |
| | * } |
| | * }</pre> |
| |*/ |
| |public class Foo() |
| """.render(java = true).description() |
| |
| val output = createHTML().body { |
| component.render(this) |
| }.trim() |
| |
| // These look the same, but pasting them into an HTML file correctly displays: |
| // |
| // fun thisIsANonPreCodeBlock() { doNotPreserveWhitespace: String \\ blah } |
| // |
| // fun thisIsAPreCodeBlock() { |
| // DOPreserveWhitespace: String \\ blah |
| // } |
| assertThat(output).isEqualTo( |
| """<body> |
| <p><code> |
| fun thisIsANonPreCodeBlock() { |
| doNotPreserveWhitespace: String \\ blah |
| } |
| </code></p> |
| <pre class="prettyprint"> |
| fun thisIsAPreCodeBlock() { |
| DOPreserveWhitespace: String \\ blah |
| } |
| </pre> |
| </body>""" |
| ) |
| } |
| |
| @Test |
| fun `table captions handled correctly`() { |
| val component = """ |
| |/** |
| | * <table> |
| | * <caption>Uri patterns and following API calls for MediaControllerCompat methods</caption> |
| | * <tr> |
| | * <th>Uri patterns</th><th>Following API calls</th><th>Method</th> |
| | * </tr><tr> |
| | * <td rowspan="2">{@code androidx://media3-session/setMediaUri?uri=[uri]}</td> |
| | * <td>{@link #prepare}</td> |
| | * <td>{@link MediaControllerCompat.TransportControls#prepareFromUri prepareFromUri} |
| | * </tr> |
| | * </tr> |
| | * </table> |
| | */ |
| |public class Foo() |
| """.render(java = true).description() |
| |
| val output = createHTML().body { |
| component.render(this) |
| }.trim() |
| |
| assertThat(output).isEqualTo( |
| """<body> |
| <table> |
| <caption>Uri patterns and following API calls for MediaControllerCompat methods</caption> |
| <tbody> |
| <tr> |
| <th>Uri patterns</th> |
| <th>Following API calls</th> |
| <th>Method</th> |
| </tr> |
| <tr> |
| <td><code>androidx://media3-session/setMediaUri?uri=[uri]</code></td> |
| <td>prepare</td> |
| <td>prepareFromUri</td> |
| </tr> |
| </tbody> |
| </table> |
| </body>""" |
| ) |
| } |
| |
| @Test // NOTE: kdoc markdown-style links do not work inside <pre> tags |
| fun `Links inside pre render correctly`() { |
| val componentJ = """ |
| |/** |
| | * a {@link Foo} |
| | * <pre> |
| | * public void onCreate() { |
| | * if (DEVELOPER_MODE) { |
| | * StrictMode.setThreadPolicy(new {@link Foo pFooey}() |
| | * .detectDiskReads() |
| | * </pre> |
| | */ |
| |public class Foo |
| """.render(java = true).description() |
| val componentK = """ |
| |/** |
| | * a [Foo] |
| | * <pre> |
| | * public void onCreate() { |
| | * if (DEVELOPER_MODE) { |
| | * StrictMode.setThreadPolicy(new [Foo]() |
| | * .detectDiskReads() |
| | * </pre> |
| | */ |
| |public class Foo |
| """.render().description() |
| |
| val outputJ = createHTML().body { |
| componentJ.render(this) |
| }.trim() |
| val outputK = createHTML().body { |
| componentK.render(this) |
| }.trim() |
| |
| // language=html |
| assertThat(outputJ).isEqualTo( |
| """ |
| <body> |
| <p>a <code><a href="/reference/androidx/example/Test.Foo.html">Foo</a></code></p> |
| <pre class="prettyprint">public void onCreate() { |
| if (DEVELOPER_MODE) { |
| StrictMode.setThreadPolicy(new <code><a href="/reference/androidx/example/Test.Foo.html">pFooey</a></code>() |
| .detectDiskReads() |
| </pre> |
| </body> |
| """.trim() |
| ) |
| // language=html |
| assertThat(outputK).isEqualTo( |
| """ |
| <body> |
| <p>a <code><a href="/reference/androidx/example/Foo.html">Foo</a></code></p> |
| <pre> |
| public void onCreate() { |
| if (DEVELOPER_MODE) { |
| StrictMode.setThreadPolicy(new [Foo]() |
| .detectDiskReads() |
| </pre></body> |
| """.trim() |
| ) |
| } |
| |
| @Test |
| fun `HTML link with docRoot renders correctly`() { |
| val component = """ |
| |/** Click <a href="{@docRoot}guide">here</a>. */ |
| |class Foo |
| """.render().description() |
| |
| val output = createHTML().body { |
| component.render(this) |
| }.trim() |
| |
| // language=html |
| assertThat(output).isEqualTo( |
| """ |
| <body> |
| <p>Click <a href="/guide">here</a>.</p> |
| </body> |
| """.trim() |
| ) |
| } |
| |
| private fun DModule.description( |
| summary: Boolean = false, |
| deprecation: String? = null |
| ): DefaultDescriptionComponent { |
| val tag = explicitClasslike("Foo").tag() |
| val (_, pathProvider) = holderAndProvider(this) |
| return DefaultDescriptionComponent( |
| Params( |
| pathProvider, |
| tag.children, |
| summary, |
| deprecation |
| ) |
| ) |
| } |
| |
| private fun Documentable.tag() = |
| documentation.values.singleOrNull()?.children.orEmpty().single().root |
| } |