From 1b97470cdfcce456124c0fd71dbb762db6d156e7 Mon Sep 17 00:00:00 2001 From: fengyangxxx <44690232+fengyangxxx@users.noreply.github.com> Date: Mon, 20 Jul 2026 23:57:50 +0800 Subject: [PATCH] docs: add Sourcey reference for Testcontainers --- docs/sourcey/css/extra.css | 128 + docs/sourcey/css/tc-header.css | 389 +++ docs/sourcey/examples.html | 41 + docs/sourcey/favicon.ico | Bin 0 -> 15406 bytes docs/sourcey/features/advanced-options.html | 97 + docs/sourcey/features/commands.html | 48 + docs/sourcey/features/configuration.html | 144 ++ docs/sourcey/features/container-logs.html | 115 + docs/sourcey/features/creating-container.html | 56 + docs/sourcey/features/creating-images.html | 96 + docs/sourcey/features/files.html | 48 + .../features/image-name-substitution.html | 158 ++ docs/sourcey/features/networking.html | 99 + docs/sourcey/features/reuse.html | 62 + docs/sourcey/features/startup-and-waits.html | 119 + docs/sourcey/icons/github.svg | 4 + docs/sourcey/icons/slack.svg | 10 + docs/sourcey/icons/stackoverflow.svg | 5 + docs/sourcey/icons/twitter.svg | 4 + docs/sourcey/index.html | 247 ++ docs/sourcey/js/tc-header.js | 45 + docs/sourcey/language-logos/dotnet.svg | 7 + docs/sourcey/language-logos/go.svg | 10 + docs/sourcey/language-logos/haskell.svg | 6 + docs/sourcey/language-logos/java.svg | 17 + docs/sourcey/language-logos/nodejs.svg | 5 + docs/sourcey/language-logos/python.svg | 8 + docs/sourcey/language-logos/ruby.svg | 125 + docs/sourcey/language-logos/rust.svg | 57 + docs/sourcey/llms-full.txt | 205 ++ docs/sourcey/llms.txt | 31 + docs/sourcey/logo.png | Bin 0 -> 67366 bytes docs/sourcey/logo.svg | 92 + docs/sourcey/modules/databases/index.html | 34 + docs/sourcey/modules/databases/jdbc.html | 132 + docs/sourcey/modules/databases/mongodb.html | 105 + docs/sourcey/modules/databases/mysql.html | 67 + docs/sourcey/modules/databases/postgres.html | 85 + docs/sourcey/modules/kafka.html | 110 + docs/sourcey/modules/localstack.html | 62 + docs/sourcey/modules/toxiproxy.html | 98 + docs/sourcey/modules_logos/hivemq-module.png | Bin 0 -> 165340 bytes .../quickstart/junit-4-quickstart.html | 92 + .../quickstart/junit-5-quickstart.html | 114 + docs/sourcey/quickstart/spock-quickstart.html | 98 + docs/sourcey/search-index.json | 1 + docs/sourcey/sitemap.xml | 29 + docs/sourcey/sourcey.css | 2210 +++++++++++++++++ docs/sourcey/sourcey.js | 1 + docs/sourcey/sponsor_logos/backbase.png | Bin 0 -> 5757 bytes docs/sourcey/sponsor_logos/cirrus_labs.jpg | Bin 0 -> 3204 bytes docs/sourcey/sponsor_logos/elastic.png | Bin 0 -> 23741 bytes docs/sourcey/sponsor_logos/jooq.jpg | Bin 0 -> 3559 bytes docs/sourcey/sponsor_logos/red_hat.png | Bin 0 -> 20118 bytes docs/sourcey/sponsor_logos/spotify.png | Bin 0 -> 4336 bytes docs/sourcey/sponsor_logos/vivy.png | Bin 0 -> 4170 bytes .../test-framework-integration/junit-5.html | 85 + docs/sourcey/testcontainers-logo.svg | 22 + 58 files changed, 5823 insertions(+) create mode 100644 docs/sourcey/css/extra.css create mode 100644 docs/sourcey/css/tc-header.css create mode 100644 docs/sourcey/examples.html create mode 100644 docs/sourcey/favicon.ico create mode 100644 docs/sourcey/features/advanced-options.html create mode 100644 docs/sourcey/features/commands.html create mode 100644 docs/sourcey/features/configuration.html create mode 100644 docs/sourcey/features/container-logs.html create mode 100644 docs/sourcey/features/creating-container.html create mode 100644 docs/sourcey/features/creating-images.html create mode 100644 docs/sourcey/features/files.html create mode 100644 docs/sourcey/features/image-name-substitution.html create mode 100644 docs/sourcey/features/networking.html create mode 100644 docs/sourcey/features/reuse.html create mode 100644 docs/sourcey/features/startup-and-waits.html create mode 100644 docs/sourcey/icons/github.svg create mode 100644 docs/sourcey/icons/slack.svg create mode 100644 docs/sourcey/icons/stackoverflow.svg create mode 100644 docs/sourcey/icons/twitter.svg create mode 100644 docs/sourcey/index.html create mode 100644 docs/sourcey/js/tc-header.js create mode 100644 docs/sourcey/language-logos/dotnet.svg create mode 100644 docs/sourcey/language-logos/go.svg create mode 100644 docs/sourcey/language-logos/haskell.svg create mode 100644 docs/sourcey/language-logos/java.svg create mode 100644 docs/sourcey/language-logos/nodejs.svg create mode 100644 docs/sourcey/language-logos/python.svg create mode 100644 docs/sourcey/language-logos/ruby.svg create mode 100644 docs/sourcey/language-logos/rust.svg create mode 100644 docs/sourcey/llms-full.txt create mode 100644 docs/sourcey/llms.txt create mode 100644 docs/sourcey/logo.png create mode 100644 docs/sourcey/logo.svg create mode 100644 docs/sourcey/modules/databases/index.html create mode 100644 docs/sourcey/modules/databases/jdbc.html create mode 100644 docs/sourcey/modules/databases/mongodb.html create mode 100644 docs/sourcey/modules/databases/mysql.html create mode 100644 docs/sourcey/modules/databases/postgres.html create mode 100644 docs/sourcey/modules/kafka.html create mode 100644 docs/sourcey/modules/localstack.html create mode 100644 docs/sourcey/modules/toxiproxy.html create mode 100644 docs/sourcey/modules_logos/hivemq-module.png create mode 100644 docs/sourcey/quickstart/junit-4-quickstart.html create mode 100644 docs/sourcey/quickstart/junit-5-quickstart.html create mode 100644 docs/sourcey/quickstart/spock-quickstart.html create mode 100644 docs/sourcey/search-index.json create mode 100644 docs/sourcey/sitemap.xml create mode 100644 docs/sourcey/sourcey.css create mode 100644 docs/sourcey/sourcey.js create mode 100644 docs/sourcey/sponsor_logos/backbase.png create mode 100644 docs/sourcey/sponsor_logos/cirrus_labs.jpg create mode 100644 docs/sourcey/sponsor_logos/elastic.png create mode 100644 docs/sourcey/sponsor_logos/jooq.jpg create mode 100644 docs/sourcey/sponsor_logos/red_hat.png create mode 100644 docs/sourcey/sponsor_logos/spotify.png create mode 100644 docs/sourcey/sponsor_logos/vivy.png create mode 100644 docs/sourcey/test-framework-integration/junit-5.html create mode 100644 docs/sourcey/testcontainers-logo.svg diff --git a/docs/sourcey/css/extra.css b/docs/sourcey/css/extra.css new file mode 100644 index 00000000000..ff780cb25ea --- /dev/null +++ b/docs/sourcey/css/extra.css @@ -0,0 +1,128 @@ +h1, h2, h3, h4, h5, h6 { + font-family: 'Rubik', sans-serif; +} + +[data-md-color-scheme="testcontainers"] { + --md-primary-fg-color: #00bac2; + --md-accent-fg-color: #361E5B; + --md-typeset-a-color: #0C94AA; + --md-primary-fg-color--dark: #291A3F; + --md-default-fg-color--lightest: #F2F4FE; + --md-footer-fg-color: #361E5B; + --md-footer-fg-color--light: #746C8F; + --md-footer-fg-color--lighter: #C3BEDE; + --md-footer-bg-color: #F7F9FD; + --md-footer-bg-color--dark: #F7F9FD; +} + +.card-grid { + display: grid; + gap: 10px; +} + +.tc-version { + font-size: 1.1em; + text-align: center; + margin: 0; +} + +@media (min-width: 680px) { + .card-grid { + grid-template-columns: repeat(3, 1fr); + } +} + +body .card-grid-item { + display: flex; + align-items: center; + gap: 20px; + border: 1px solid #C3BEDE; + border-radius: 6px; + padding: 16px; + font-weight: 600; + color: #9991B5; + background: #F2F4FE; +} + +body .card-grid-item:hover, +body .card-grid-item:focus { + color: #9991B5; +} + +.card-grid-item[href] { + color: var(--md-primary-fg-color--dark); + background: transparent; +} + +.card-grid-item[href]:hover, +.card-grid-item[href]:focus { + background: #F2F4FE; + color: var(--md-primary-fg-color--dark); +} + +.community-callout-wrapper { + padding: 30px 10px 0 10px; +} + +.community-callout { + color: #F2F4FE; + background: linear-gradient(10.88deg, rgba(102, 56, 242, 0.4) 9.56%, #6638F2 100%), #291A3F; + box-shadow: 0px 20px 45px rgba(#9991B5, 0.75); + border-radius: 10px; + padding: 20px; +} + +.community-callout h2 { + font-size: 1.15em; + margin: 0 0 20px 0; + color: #F2F4FE; + text-align: center; +} + +.community-callout ul { + list-style: none; + padding: 0; + display: flex; + justify-content: space-between; + gap: 10px; + margin-top: 20px; + margin-bottom: 0; +} + +.community-callout a { + transition: opacity 0.2s ease; +} + +.community-callout a:hover { + opacity: 0.5; +} + +.community-callout a img { + height: 1.75em; + width: auto; + aspect-ratio: 1; +} + +@media (min-width: 1220px) { + .community-callout-wrapper { + padding: 40px 0 0; + } + + .community-callout h2 { + font-size: 1.25em; + } + + .community-callout a img { + height: 2em; + } +} + +@media (min-width: 1600px) { + .community-callout h2 { + font-size: 1.15em; + } + + .community-callout a img { + height: 1.75em; + } +} \ No newline at end of file diff --git a/docs/sourcey/css/tc-header.css b/docs/sourcey/css/tc-header.css new file mode 100644 index 00000000000..de78d636e9c --- /dev/null +++ b/docs/sourcey/css/tc-header.css @@ -0,0 +1,389 @@ + +:root { + --color-catskill: #F2F4FE; + --color-catskill-45: rgba(242, 244, 254, 0.45); + --color-mist: #E7EAFB; + --color-fog: #C3C7E6; + --color-smoke: #9991B5; + --color-smoke-75: rgba(153, 145, 181, 0.75); + --color-storm: #746C8F; + --color-topaz: #00BAC2; + --color-pacific: #17A6B2; + --color-teal: #027F9E; + --color-eggplant: #291A3F; + --color-plum: #361E5B; + +} + +#site-header { + color: var(--color-storm); + background: #fff; + font-family: 'Rubik', Arial, Helvetica, sans-serif; + font-size: 12px; + line-height: 1.5; + position: relative; + width: 100%; + z-index: 4; + display: flex; + align-items: center; + justify-content: space-between; + gap: 20px; + padding: 20px; +} + +body.tc-header-active #site-header { + z-index: 5; +} + +#site-header .brand { + display: flex; + justify-content: space-between; + gap: 20px; + width: 100%; +} + +#site-header .logo { + display: flex; +} + +#site-header .logo img, +#site-header .logo svg { + height: 30px; + width: auto; + max-width: 100%; +} + +#site-header #mobile-menu-toggle { + background: none; + border: none; + display: flex; + align-items: center; + gap: 10px; + cursor: pointer; + color: var(--color-eggplant); + padding: 0; + margin: 0; + font-weight: 500; +} + +body.mobile-menu #site-header #mobile-menu-toggle { + color: var(--color-topaz); +} + +#site-header ul { + list-style: none; + padding: 0; + margin: 0; +} + +#site-header nav { + display: none; +} + +#site-header .menu-item { + display: flex; +} + +#site-header .menu-item button, +#site-header .menu-item a { + min-height: 30px; + display: flex; + gap: 6px; + align-items: center; + border: none; + background: none; + cursor: pointer; + padding: 0; + font-weight: 500; + color: var(--color-eggplant); + text-decoration: none; + font-size: 14px; + transition: color 0.2s ease; + white-space: nowrap; +} + +#site-header .menu-item .badge { + color: white; + font-size: 10px; + padding: 2px 6px; + background-color: #0FD5C6; // somehow $topaz is too dark for me. +text-align: center; + text-decoration: none; + display: inline-block; + border-radius: 6px; + &:hover { + + } +} + +#site-header .menu-item button:hover, +#site-header .menu-item a:hover { + color: var(--color-topaz); +} + +#site-header .menu-item button .icon-external, +#site-header .menu-item a .icon-externa { + margin-left: auto; + opacity: .3; + flex-shrink: 0; +} + +#site-header .menu-item button .icon-caret, +#site-header .menu-item a .icon-caret { + opacity: .3; + height: 8px; +} + +#site-header .menu-item button .icon-slack, +#site-header .menu-item a .icon-slack, +#site-header .menu-item button .icon-github, +#site-header .menu-item a .icon-github { + height: 18px; +} + +#site-header .menu-item .menu-dropdown { + flex-direction: column; +} + +body #site-header .menu-item .menu-dropdown { + display: none; +} + +#site-header .menu-item.has-children.active .menu-dropdown { + display: flex; + z-index: 10; +} + +#site-header .menu-dropdown-item + .menu-dropdown-item { + border-top: 1px solid var(--color-mist); +} + +#site-header .menu-dropdown-item a { + display: flex; + gap: 10px; + align-items: center; + padding: 10px 20px; + font-weight: 500; + color: var(--color-eggplant); + text-decoration: none; + transition: + color 0.2s ease, + background 0.2s ease; +} + +#site-header .menu-dropdown-item a .icon-external { + margin-left: auto; + color: var(--color-fog); + flex-shrink: 0; + opacity: 1; +} + +#site-header .menu-dropdown-item a:hover { + background-color: var(--color-catskill-45); +} + +#site-header .menu-dropdown-item a:hover .icon-external { + color: var(--color-topaz); +} + +#site-header .menu-dropdown-item a img { + height: 24px; +} + +.md-header { + background-color: var(--color-catskill); + color: var(--color-eggplant); +} + +.md-header.md-header--shadow { + box-shadow: none; +} + +.md-header__inner.md-grid { + max-width: 100%; + padding: 1.5px 20px; +} + +[dir=ltr] .md-header__title { + margin: 0; +} + +.md-header__topic:first-child { + font-size: 16px; + font-weight: 500; + font-family: 'Rubik', Arial, Helvetica, sans-serif; +} + +.md-header__title.md-header__title--active .md-header__topic, +.md-header__title[data-md-state=active] .md-header__topic { + opacity: 1; + pointer-events: all; + transform: translateX(0); + transition: none; + z-index: 0; +} + +.md-header__topic a { + max-width: 100%; + overflow: hidden; + text-overflow: ellipsis; + transition: color .2s ease; +} + +.md-header__topic a:hover { + color: var(--color-topaz); +} + +div.md-header__source { + width: auto; +} + +div.md-source__repository { + max-width: 100%; +} + +.md-main { + padding: 0 12px; +} + +@media screen and (min-width: 60em) { + form.md-search__form { + background-color: #FBFBFF; + color: var(--color-storm); + } + + form.md-search__form:hover { + background-color: #fff; + } + + .md-search__input + .md-search__icon { + color: var(--color-plum); + } + + .md-search__input::placeholder { + color: var(--color-smoke); + } +} + +@media (min-width: 500px) { + #site-header { + font-size: 16px; + padding: 20px 40px; + } + #site-header .logo img, + #site-header .logo svg { + height: 48px; + } + + #site-header .menu-item button .icon-caret, + #site-header .menu-item a .icon-caret { + height: 10px; + } + + #site-header .menu-item button .icon-slack, + #site-header .menu-item a .icon-slack, + #site-header .menu-item button .icon-github, + #site-header .menu-item a .icon-github { + height: 24px; + } + + .md-header__inner.md-grid { + padding: 5px 40px; + } + + .md-main { + padding: 0 32px; + } +} + +@media (min-width: 1024px) { + #site-header #mobile-menu-toggle { + display: none; + } + + #site-header nav { + display: block; + } + + #site-header .menu { + display: flex; + justify-content: center; + gap: 30px; + } + + #site-header .menu-item { + align-items: center; + position: relative; + } + + #site-header .menu-item button, + #site-header .menu-item a { + min-height: 48px; + gap: 8px; + font-size: 16px; + } + + #site-header .menu-item .menu-dropdown { + position: absolute; + top: 100%; + right: -8px; + border: 1px solid var(--color-mist); + border-radius: 6px; + background: #fff; + box-shadow: 0px 30px 35px var(--color-smoke-75); + min-width: 200px; + } +} + + +@media (max-width: 1023px) { + #site-header { + flex-direction: column; + } + + body.mobile-tc-header-active #site-header { + z-index: 5; + } + + body.mobile-menu #site-header nav { + display: flex; + } + + #site-header nav { + position: absolute; + top: calc(100% - 5px); + width: calc(100% - 80px); + flex-direction: column; + border: 1px solid var(--color-mist); + border-radius: 6px; + background: #fff; + box-shadow: 0px 30px 35px var(--color-smoke-75); + min-width: 200px; + } + + #site-header .menu-item { + flex-direction: column; + } + #site-header .menu-item + .menu-item { + border-top: 1px solid var(--color-mist); + } + + #site-header .menu-item button, + #site-header .menu-item a { + padding: 10px 20px; + } + + #site-header .menu-item.has-children.active .menu-dropdown { + border-top: 1px solid var(--color-mist); + } + + #site-header .menu-dropdown-item a { + padding: 10px 20px 10px 30px; + } +} + +@media (max-width: 499px) { + #site-header nav { + width: calc(100% - 40px); + } +} diff --git a/docs/sourcey/examples.html b/docs/sourcey/examples.html new file mode 100644 index 00000000000..f646e6e923a --- /dev/null +++ b/docs/sourcey/examples.html @@ -0,0 +1,41 @@ + +Examples - Testcontainers for Java Sourcey Reference
Pages

Examples

Examples of different use cases provided by Testcontainers can be found below:
\ No newline at end of file diff --git a/docs/sourcey/favicon.ico b/docs/sourcey/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..311a0acaa373f197360673f8ac6bc1b3c38c7e7f GIT binary patch literal 15406 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 +Advanced options - Testcontainers for Java Sourcey Reference
Core concepts

Advanced options

To add a custom label to the container, use withLabel:

Container labels

+

To add a custom label to the container, use withLabel:

+ +

Adding a single label inside_block:single_label

+ + +

Additionally, multiple labels may be applied together from a map:

+ +

Adding multiple labels inside_block:multiple_labels

+ + +

Image Pull Policy

+

By default, the container image is retrieved from the local Docker images cache. +This works well when running against a specific version, but for images with a static tag (i.e. 'latest') this may lead to a newer version not being pulled.

+

It is possible to specify an Image Pull Policy to determine at runtime whether an image should be pulled or not:

+ +

Setting image pull policy inside_block:built_in_image_pull_policy

+ + +

... or providing a function:

+ +

Custom image pull policy inside_block:custom_image_pull_policy

+ + +

You can also configure Testcontainers to use your custom implementation by using pull.policy

+

src/test/resources/testcontainers.properties

+
+
+ +
+
pull.policy=com.mycompany.testcontainers.ExampleImagePullPolicy
+

You can also use the provided implementation to always pull images

+

src/test/resources/testcontainers.properties

+
+
+ +
+
pull.policy=org.testcontainers.images.AlwaysPullPolicy
+

Please see the documentation on configuration mechanisms for more information.

+

Customizing the container

+

Using docker-java

+

It is possible to use the docker-java API directly to customize containers before creation. This is useful if there is a need to use advanced Docker features that are not exposed by the Testcontainers API. Any customizations you make using withCreateContainerCmdModifier will be applied on top of the container definition that Testcontainers creates, but before it is created.

+

For example, this can be used to change the container hostname:

+ +

Using modifier to change hostname inside_block:hostname

+ + +

... or modify container memory (see this if it does not appear to work):

+ +

Using modifier to change memory limits inside_block:memory

+ + +
+

Note +It is recommended to use this sparingly, and follow changes to the docker-java API if you choose to use this. +It is typically quite stable, though.

+
+

For what is possible, consult the docker-java CreateContainerCmd source code.

+

Using CreateContainerCmdModifier

+

Testcontainers provides a CreateContainerCmdModifier to customize docker-java CreateContainerCmd +via Service Provider Interface (SPI) mechanism.

+ +

CreateContainerCmd example implementation

+ + +

The previous implementation should be registered in META-INF/services/org.testcontainers.core.CreateContainerCmdModifier file.

+
+

Warning +CreateContainerCmdModifier implementation will apply to all containers created by Testcontainers.

+
+

Parallel Container Startup

+

Usually, containers are started sequentially when more than one container is used. +Using Startables.deepStart(container1, container2, ...).join() will start all containers in parallel. +This can be advantageous to reduce the impact of the container startup overhead.

+
\ No newline at end of file diff --git a/docs/sourcey/features/commands.html b/docs/sourcey/features/commands.html new file mode 100644 index 00000000000..a629cbe7eb5 --- /dev/null +++ b/docs/sourcey/features/commands.html @@ -0,0 +1,48 @@ + +Executing commands - Testcontainers for Java Sourcey Reference
Core concepts

Executing commands

By default the container will execute whatever command is specified in the image's Dockerfile. To override this, and specify a different command, use withCommand. For example:

Container startup command

+

By default the container will execute whatever command is specified in the image's Dockerfile. To override this, and specify a different command, use withCommand. For example:

+ +

Specifying a startup command inside_block:startupCommand

+ + +

Executing a command

+

Your test can execute a command inside a running container, similar to a docker exec call:

+ +

Executing a command inside a running container inside_block:standaloneExec

+ + +

This can be useful for software that has a command line administration tool. You can also get the output (stdout/stderr) and exit code from the command - for example:

+ +

Executing a command inside a running container and reading the result inside_block:execReadingStdout

+ + +

Environment variables

+

To add environment variables to the container, use withEnv:

+
+
+ +
+
new GenericContainer(...)
+		.withEnv("API_TOKEN", "foo")
+
\ No newline at end of file diff --git a/docs/sourcey/features/configuration.html b/docs/sourcey/features/configuration.html new file mode 100644 index 00000000000..648ed8cb636 --- /dev/null +++ b/docs/sourcey/features/configuration.html @@ -0,0 +1,144 @@ + +Custom configuration - Testcontainers for Java Sourcey Reference
Core concepts

Custom configuration

You can override some default properties if your environment requires that.

You can override some default properties if your environment requires that.

+

Configuration locations

+

The configuration will be loaded from multiple locations. Properties are considered in the following order:

+
    +
  1. Environment variables
  2. +
  3. .testcontainers.properties in user's home folder. Example locations:
    Linux: /home/myuser/.testcontainers.properties
    Windows: C:/Users/myuser/.testcontainers.properties
    macOS: /Users/myuser/.testcontainers.properties
  4. +
  5. testcontainers.properties on the classpath.
  6. +
+

Note that when using environment variables, configuration property names should be set in upper +case with underscore separators, preceded by TESTCONTAINERS_ - e.g. checks.disable becomes +TESTCONTAINERS_CHECKS_DISABLE.

+

The classpath testcontainers.properties file may exist within the local codebase (e.g. within the src/test/resources directory) or within library dependencies that you may have. +Any such configuration files will have their contents merged. +If any keys conflict, the value will be taken on the basis of the first value found in:

+
    +
  • 'local' classpath (i.e. where the URL of the file on the classpath begins with file:), then
  • +
  • other classpath locations (i.e. JAR files) - considered in alphabetical order of path to provide deterministic ordering.
  • +
+

Disabling the startup checks

+
+

checks.disable = [true|false]

+
+

Before running any containers Testcontainers will perform a set of startup checks to ensure that your environment is configured correctly. Usually they look like this:

+
+
+ +
+
        ℹ︎ Checking the system...
+        ✔ Docker version should be at least 1.6.0
+        ✔ File should be mountable
+        ✔ A port exposed by a docker container should be accessible
+

It takes a couple of seconds, but if you want to speed up your tests, you can disable the checks once you have everything configured. Add checks.disable=true to your $HOME/.testcontainers.properties to completely disable them.

+

Customizing images

+
+

Note +This approach is discouraged and deprecated, but is documented for completeness. +Overriding individual image names via configuration may be removed in 2021. +See Image Name Substitution for other strategies for substituting image names to pull from other registries.

+
+

Testcontainers uses public Docker images to perform different actions like startup checks, VNC recording and others. +Some companies disallow the usage of Docker Hub, but you can override *.image properties with your own images from your private registry to workaround that.

+
+

ryuk.container.image = testcontainers/ryuk:0.3.3 +Performs fail-safe cleanup of containers, and always required (unless Ryuk is disabled)

+
+
+

tinyimage.container.image = alpine:3.17
Used to check whether images can be pulled at startup, and always required (unless startup checks are disabled)

+
+
+

sshd.container.image = testcontainers/sshd:1.4.0
Required if exposing host ports to containers

+
+
+

vncrecorder.container.image = testcontainers/vnc-recorder:1.3.0 +Used by VNC recorder in Testcontainers' Selenium integration

+
+
+

socat.container.image = alpine/socat
compose.container.image = docker/compose:1.8.0
Required if using Docker Compose

+
+
+

kafka.container.image = confluentinc/cp-kafka
Used by KafkaContainer

+
+
+

localstack.container.image = localstack/localstack
Used by LocalStack

+
+
+

pulsar.container.image = apachepulsar/pulsar:2.2.0
Used by Apache Pulsar

+
+

Customizing Ryuk resource reaper

+
+

ryuk.container.image = testcontainers/ryuk:0.3.3 +The resource reaper is responsible for container removal and automatic cleanup of dead containers at JVM shutdown

+
+
+

ryuk.container.privileged = true +In some environments ryuk must be started in privileged mode to work properly (--privileged flag)

+
+

Disabling Ryuk

+

Ryuk must be started as a privileged container.
If your environment already implements automatic cleanup of containers after the execution, +but does not allow starting privileged containers, you can turn off the Ryuk container by setting +TESTCONTAINERS_RYUK_DISABLED environment variable to true.

+

!!!tip + Note that Testcontainers will continue doing the cleanup at JVM's shutdown, unless you kill -9 your JVM process.

+

Customizing image pull behaviour

+
+

pull.timeout = 120 +By default Testcontainers will timeout if pull takes more than this duration (in seconds)

+
+
+

pull.pause.timeout = 30 +By default Testcontainers will abort the pull of an image if the pull appears stalled (no data transferred) for longer than this duration (in seconds).

+
+

Customizing client ping behaviour

+
+

client.ping.timeout = 10 +Specifies for how long Testcontainers will try to connect to the Docker client to obtain valid info about the client before giving up and trying next strategy, if applicable (in seconds).

+
+

Customizing Docker host detection

+

Testcontainers will attempt to detect the Docker environment and configure everything to work automatically.

+

However, sometimes customization is required. Testcontainers will respect the following environment variables:

+
+

DOCKER_HOST = unix:///var/run/docker.sock
See Docker environment variables

+

TESTCONTAINERS_DOCKER_SOCKET_OVERRIDE
Path to Docker's socket. Used by Ryuk, Docker Compose, and a few other containers that need to perform Docker actions.
Example: /var/run/docker-alt.sock

+

TESTCONTAINERS_HOST_OVERRIDE
Docker's host on which ports are exposed.
Example: docker.svc.local

+
+

For advanced users, the Docker host connection can be configured via configuration in ~/.testcontainers.properties. +Note that these settings require use of the EnvironmentAndSystemPropertyClientProviderStrategy. The example below +illustrates usage:

+
+
+ +
+
docker.client.strategy=org.testcontainers.dockerclient.EnvironmentAndSystemPropertyClientProviderStrategy
+docker.host=tcp\://my.docker.host\:1234     # Equivalent to the DOCKER_HOST environment variable. Colons should be escaped.
+docker.tls.verify=1                         # Equivalent to the DOCKER_TLS_VERIFY environment variable
+docker.cert.path=/some/path                 # Equivalent to the DOCKER_CERT_PATH environment variable
+

In addition, you can deactivate this behaviour by specifying:

+
+
+ +
+
dockerconfig.source=autoIgnoringUserProperties # 'auto' by default
+
\ No newline at end of file diff --git a/docs/sourcey/features/container-logs.html b/docs/sourcey/features/container-logs.html new file mode 100644 index 00000000000..8e63edc16fa --- /dev/null +++ b/docs/sourcey/features/container-logs.html @@ -0,0 +1,115 @@ + +Accessing container logs - Testcontainers for Java Sourcey Reference
Core concepts

Accessing container logs

It is possible to capture container output using:

It is possible to capture container output using:

+
    +
  • the getLogs() method, which simply returns a String snapshot of a container's entire log output
  • +
  • the followOutput() method. This method accepts a Consumer and (optionally) +a varargs list stating which of STDOUT, STDERR, or both, should be followed. If not specified, both will be followed.
  • +
+

At present, container output will always begin from the time of container creation.

+

Reading all logs (from startup time to present)

+

getLogs() is the simplest mechanism for accessing container logs, and can be used as follows:

+ +

Accessing all output (stdout and stderr) inside_block:docsGetAllLogs

+ + + +

Accessing just stdout inside_block:docsGetStdOut

+ + + +

Accessing just stderr inside_block:docsGetStdErr

+ + +

Streaming logs

+

Testcontainers includes some out-of-the-box Consumer implementations that can be used with the streaming followOutput() model; examples follow.

+

Streaming container output to an SLF4J logger

+

Given an existing SLF4J logger instance named LOGGER:

+
+
+ +
+
Slf4jLogConsumer logConsumer = new Slf4jLogConsumer(LOGGER);
+container.followOutput(logConsumer);
+

By default both standard out and standard error will both be emitted at INFO level. +Standard error may be emitted at ERROR level, if desired:

+
+
+ +
+
Slf4jLogConsumer logConsumer = new Slf4jLogConsumer(LOGGER).withSeparateOutputStreams();
+

The Mapped Diagnostic Context (MDC) for emitted messages may be configured using the withMdc(...) option:

+
+
+ +
+
Slf4jLogConsumer logConsumer = new Slf4jLogConsumer(LOGGER).withMdc("key", "value");
+

or using an existing map of key-value pairs:

+
+
+ +
+
Slf4jLogConsumer logConsumer = new Slf4jLogConsumer(LOGGER).withMdc(map);
+

Capturing container output as a String

+

To stream logs live or customize the decoding, ToStringConsumer may be used:

+
+
+ +
+
ToStringConsumer toStringConsumer = new ToStringConsumer();
+container.followOutput(toStringConsumer, OutputType.STDOUT);
+
+String utf8String = toStringConsumer.toUtf8String();
+
+// Or if the container output is not UTF-8
+String otherString = toStringConsumer.toString(CharSet.forName("ISO-8859-1"));
+

Waiting for container output to contain expected content

+

WaitingConsumer will block until a frame of container output (usually a line) matches a provided predicate.

+

A timeout may be specified, as shown in this example.

+
+
+ +
+
WaitingConsumer consumer = new WaitingConsumer();
+
+container.followOutput(consumer, STDOUT);
+
+consumer.waitUntil(frame -> 
+    frame.getUtf8String().contains("STARTED"), 30, TimeUnit.SECONDS);
+

Additionally, as the Java 8 Consumer functional interface is used, Consumers may be composed together. This is +useful, for example, to capture all the container output but only when a matching string has been found. e.g.:

+
+
+ +
+
WaitingConsumer waitingConsumer = new WaitingConsumer();
+ToStringConsumer toStringConsumer = new ToStringConsumer();
+
+Consumer&lt;OutputFrame&gt; composedConsumer = toStringConsumer.andThen(waitingConsumer);
+container.followOutput(composedConsumer);
+
+waitingConsumer.waitUntil(frame -> 
+    frame.getUtf8String().contains("STARTED"), 30, TimeUnit.SECONDS);
+
+String utf8String = toStringConsumer.toUtf8String();
+
\ No newline at end of file diff --git a/docs/sourcey/features/creating-container.html b/docs/sourcey/features/creating-container.html new file mode 100644 index 00000000000..25489ac794d --- /dev/null +++ b/docs/sourcey/features/creating-container.html @@ -0,0 +1,56 @@ + +Creating a container - Testcontainers for Java Sourcey Reference
Core concepts

Creating a container

Testcontainers' generic container support offers the most flexibility, and makes it easy to use virtually any container images as temporary test dependencies. For example, if you might use it to test interactions with:

Creating a generic container based on an image

+

Testcontainers' generic container support offers the most flexibility, and makes it easy to use virtually any container +images as temporary test dependencies. For example, if you might use it to test interactions with:

+
    +
  • NoSQL databases or other data stores (e.g. redis, elasticsearch, mongo)
  • +
  • Web servers/proxies (e.g. nginx, apache)
  • +
  • Log services (e.g. logstash, kibana)
  • +
  • Other services developed by your team/organization which are already dockerized
  • +
+

With a generic container, you set the container image using a parameter to the rule constructor, e.g.:

+
+
+ +
+
new GenericContainer(DockerImageName.parse("jboss/wildfly:9.0.1.Final"))
+

Specifying an image

+

Many Container classes in Testcontainers have historically supported:

+
    +
  • a no-args constructor - for example new GenericContainer() and new ElasticsearchContainer(). With these constructors, Testcontainers has traditionally used a default image name (including a fixed image tag/version). This has caused a conflict between the need to keep the defaults sane (i.e. up to date) and the need to avoid silently upgrading these dependencies along with new versions of Testcontainers.
  • +
  • a single string-argument constructor, which has taken either a version or an image name as a String. This has caused some ambiguity and confusion.
  • +
+

Since v1.15.0, both of these constructor types have been deprecated, for the reasons given above.

+

Instead, it is highly recommended that all containers be constructed using a constructor that accepts a DockerImageName object. +The DockerImageName class is an unambiguous reference to a docker image.

+

It is suggested that developers treat DockerImageNames as you would any other potentially-constant value - consider defining a constant in your test codebase that matches the production version of the dependency you are using.

+

Examples

+

A generic container rule can be used with any public docker image; for example:

+ +

Creating a Redis container inside_block:container

+ + +

The container, as @Container, will be started before any tests in the class run, and will be destroyed after all +tests have run.

+
\ No newline at end of file diff --git a/docs/sourcey/features/creating-images.html b/docs/sourcey/features/creating-images.html new file mode 100644 index 00000000000..1a543913572 --- /dev/null +++ b/docs/sourcey/features/creating-images.html @@ -0,0 +1,96 @@ + +Creating images on-the-fly - Testcontainers for Java Sourcey Reference
Core concepts

Creating images on-the-fly

In situations where there is no pre-existing Docker image, Testcontainers can create a new temporary image on-the-fly from a Dockerfile. For example, when the component under test is the Docker image itself, or when an existing base image needs to be customized for specific test(s).

Overview

+

In situations where there is no pre-existing Docker image, Testcontainers can create a new temporary image on-the-fly +from a Dockerfile. For example, when the component under test is the Docker image itself, or when an existing base +image needs to be customized for specific test(s).

+

Simply pass a configured instance of ImageFromDockerfile as a constructor parameter to GenericContainer. +Testcontainers will docker build a temporary container image, and will use it when creating the container.

+

Dockerfile from String, file or classpath resource

+

ImageFromDockerfile accepts arbitrary files, strings or classpath resources to be used as files in the build context. +At least one of these needs to be a Dockerfile.

+
+
+ +
+
GenericContainer container = new GenericContainer(
+    new ImageFromDockerfile()
+            .withFileFromString("folder/someFile.txt", "hello")
+            .withFileFromClasspath("test.txt", "mappable-resource/test-resource.txt")
+            .withFileFromClasspath("Dockerfile", "mappable-dockerfile/Dockerfile"))
+

The following methods may be used to provide the Dockerfile and any other required build context files:

+
    +
  • withFileFromString(buildContextPath, content)
  • +
  • withFileFromClasspath(buildContextPath, classpathPath)
  • +
  • withFileFromPath(buildContextPath, filesystemPath)
  • +
  • withFileFromFile(buildContextPath, filesystemFile)
  • +
+
+

Info +In older versions of Testcontainers (before 1.3.0) it was necessary to explicitly declare each file that needed to +be present in the Docker build context. +This can be replaced with the following syntax:

+ +

Passing an entire directory of files to the Dockerfile build context inside_block:docsShowRecursiveFileInclusion

+ + +

Where RESOURCE_PATH is the path to a directory containing a Dockerfile and any files that it needs to refer to. +Doing this is equivalent to docker build RESOURCE_PATH on the command line.

+

To mimic docker build ., RESOURCE_PATH would simply be set to . as well.

+
+

Dockerfile DSL

+

If a static Dockerfile is not sufficient (e.g. your test needs to cover many variations that are best generated +programmatically), there is a DSL available to allow Dockerfiles to be defined in code. e.g.:

+
+
+ +
+
new GenericContainer(
+        new ImageFromDockerfile()
+                .withDockerfileFromBuilder(builder ->
+                        builder
+                                .from("alpine:3.17")
+                                .run("apk add --update nginx")
+                                .cmd("nginx", "-g", "daemon off;")
+                                .build()))
+                .withExposedPorts(80);
+

See ParameterizedDockerfileContainerTest for a very basic example of using this in conjunction with JUnit +parameterized testing.

+

Automatic deletion

+

Temporary container images will be automatically removed when the test JVM shuts down. If this is not desired and +the image should be retained between tests, pass a stable image name and false flag to the ImageFromDockerfile +constructor.

+

Retaining the image between tests will use Docker's image cache to accelerate subsequent test runs.

+

By default the no-args constructor will use an image name of the form testcontainers/ + random string:

+
    +
  • public ImageFromDockerfile()
  • +
  • public ImageFromDockerfile(String dockerImageName)
  • +
  • public ImageFromDockerfile(String dockerImageName, boolean deleteOnExit)
  • +
+

Alternative Dockerfiles

+

Normally Docker will automatically build an image from any /Dockerfile that it finds in the root of the build context. +To override this behaviour, use .withDockerfilePath("./Name-Of-Other-Dockerfile").

+

Build Args

+

Build Args may be used to allow lightweight parameterization.

+

To specify build args, use .withBuildArg("varname", "value") or provide a Map of args using .withBuildArgs(map).

+
\ No newline at end of file diff --git a/docs/sourcey/features/files.html b/docs/sourcey/features/files.html new file mode 100644 index 00000000000..61aa84b6a14 --- /dev/null +++ b/docs/sourcey/features/files.html @@ -0,0 +1,48 @@ + +Files and volumes - Testcontainers for Java Sourcey Reference
Core concepts

Files and volumes

Files can be copied into the container before startup, or can be copied from the container after the container has started.

Copying files

+

Files can be copied into the container before startup, or can be copied from the container after the container has started.

+
+

Note +This is the recommended approach for portability cross-docker environments.

+
+

Copying to a container before startup

+ +

Copying files using MountableFile inside_block:copyToContainer

+ + +

Using Transferable, file content will be placed in the specified location.

+ +

Copying files using Transferable inside_block:transferableFile

+ + +

Setting file mode is also possible.

+ +

Copying files using Transferable with file mode inside_block:transferableWithFileMode

+ + +

Copying a file from a running container

+ +

Copying files from a container inside_block:copyFileFromContainer

+ +
\ No newline at end of file diff --git a/docs/sourcey/features/image-name-substitution.html b/docs/sourcey/features/image-name-substitution.html new file mode 100644 index 00000000000..57a377e3827 --- /dev/null +++ b/docs/sourcey/features/image-name-substitution.html @@ -0,0 +1,158 @@ + +Image name substitution - Testcontainers for Java Sourcey Reference
Core concepts

Image name substitution

Testcontainers supports automatic substitution of Docker image names.

Testcontainers supports automatic substitution of Docker image names.

+

This allows replacement of an image name specified in test code with an alternative name - for example, to replace the +name of a Docker Hub image dependency with an alternative hosted on a private image registry.

+

This is advisable to avoid Docker Hub rate limiting, and some companies will prefer this for policy reasons.

+

This page describes four approaches for image name substitution:

+ +

It is assumed that you have already set up a private registry hosting all the Docker images your build requires.

+

Manual substitution

+

Consider this if:

+
    +
  • You use only a few images and updating code is not a chore
  • +
  • All developers and CI machines in your organisation have access to a common registry server
  • +
  • You also use one of the automated mechanisms to substitute the images that Testcontainers itself requires
  • +
+

This approach simply entails modifying test code manually, e.g. changing:

+

For example, you may have a test that uses the mysql container image from Docker Hub:

+ +

Direct Docker Hub image name inside_block:directDockerHubReference

+ + +

to:

+ +

Private registry image name inside_block:hardcodedMirror

+ + + + + + +

Automatically modifying Docker Hub image names

+

Testcontainers can be configured to modify Docker Hub image names on the fly to apply a prefix string.

+

Consider this if:

+
    +
  • Developers and CI machines need to use different image names. For example, developers are able to pull images from Docker Hub, but CI machines need to pull from a private registry
  • +
  • Your private registry has copies of images from Docker Hub where the names are predictable, and just adding a prefix is enough. +For example, registry.mycompany.com/mirror/mysql:8.0.36 can be derived from the original Docker Hub image name (mysql:8.0.36) with a consistent prefix string: registry.mycompany.com/mirror/
  • +
+

In this case, image name references in code are unchanged. +i.e. you would leave as-is:

+ +

Unchanged direct Docker Hub image name inside_block:directDockerHubReference

+ + +

You can then configure Testcontainers to apply the prefix registry.mycompany.com/mirror/ to every image that it tries to pull from Docker Hub. +This can be done in one of two ways:

+
    +
  • Setting environment variables TESTCONTAINERS_HUB_IMAGE_NAME_PREFIX=registry.mycompany.com/mirror/
  • +
  • Via config file, setting hub.image.name.prefix in either:
      +
    • the ~/.testcontainers.properties file in your user home directory, or
    • +
    • a file named testcontainers.properties on the classpath
    • +
    +
  • +
+

Testcontainers will automatically apply the prefix to every image that it pulls from Docker Hub - please verify that all the required images exist in your registry.

+

Testcontainers will not apply the prefix to:

+
    +
  • non-Hub image names (e.g. where another registry is set)
  • +
  • Docker Hub image names where the hub registry is explicitly part of the name (i.e. anything with a docker.io or registry.hub.docker.com host part)
  • +
+

Developing a custom function for transforming image names on the fly

+

Consider this if:

+
    +
  • You have complex rules about which private registry images should be used as substitutes, e.g.:
      +
    • non-deterministic mapping of names meaning that a name prefix cannot be used
    • +
    • rules depending upon developer identity or location
    • +
    +
  • +
  • or you wish to add audit logging of images used in the build
  • +
  • or you wish to prevent accidental usage of images that are not on an approved list
  • +
+

In this case, image name references in code are unchanged. +i.e. you would leave as-is:

+ +

Unchanged direct Docker Hub image name inside_block:directDockerHubReference

+ + +

You can implement a custom image name substitutor by:

+
    +
  • subclassing org.testcontainers.utility.ImageNameSubstitutor
  • +
  • configuring Testcontainers to use your custom implementation
  • +
+

The following is an example image substitutor implementation:

+ +

Example Image Substitutor block:ExampleImageNameSubstitutor

+ + +

Testcontainers can be configured to find it at runtime via configuration. +To do this, create or modify a file on the classpath named testcontainers.properties.

+

For example:

+

src/test/resources/testcontainers.properties

+
+
+ +
+
image.substitutor=com.mycompany.testcontainers.ExampleImageNameSubstitutor
+

Note that it is also possible to provide this same configuration property:

+
    +
  • in a testcontainers.properties file at the root of a library JAR file (useful if you wish to distribute a drop-in image substitutor JAR within an organization)
  • +
  • in a properties file in the user's home directory (~/.testcontainers.properties; note the leading .)
  • +
  • or as an environment variable (e.g. TESTCONTAINERS_IMAGE_SUBSTITUTOR=com.mycompany.testcontainers.ExampleImageNameSubstitutor).
  • +
+

Please see the documentation on configuration mechanisms for more information.

+

Also, you can use the ServiceLoader mechanism to provide the fully qualified class name of the ImageNameSubstitutor implementation:

+

src/test/resources/META-INF/services/org.testcontainers.utility.ImageNameSubstitutor

+
+
+ +
+
com.mycompany.testcontainers.ExampleImageNameSubstitutor
+

Overriding image names individually in configuration

+
+

Note +This approach is discouraged and deprecated, but is documented for completeness. +Please consider one of the other approaches outlined in this page instead. +Overriding individual image names via configuration may be removed in the future.

+
+

Consider this if:

+
    +
  • You have many references to image names in code and changing them is impractical, and
  • +
  • None of the other options are practical for you
  • +
+

In this case, image name references in code are left unchanged. +i.e. you would leave as-is:

+ +

Unchanged direct Docker Hub image name inside_block:directDockerHubReference

+ + +

You can force Testcontainers to substitute in a different image using a configuration file, which allows some (but not all) container names to be substituted.

+
\ No newline at end of file diff --git a/docs/sourcey/features/networking.html b/docs/sourcey/features/networking.html new file mode 100644 index 00000000000..0d13100903b --- /dev/null +++ b/docs/sourcey/features/networking.html @@ -0,0 +1,99 @@ + +Networking and communicating with containers - Testcontainers for Java Sourcey Reference
Core concepts

Networking and communicating with containers

It is common to want to connect to a container from your test process, running on the test 'host' machine. For example, you may be testing a class that needs to connect to a backend or data store container.

Exposing container ports to the host

+

It is common to want to connect to a container from your test process, running on the test 'host' machine. +For example, you may be testing a class that needs to connect to a backend or data store container.

+

Generally, each required port needs to be explicitly exposed. For example, we can specify one or more ports as follows:

+ +

Exposing ports inside_block:rule

+ + +

Note that this exposed port number is from the perspective of the container.

+

From the host's perspective Testcontainers actually exposes this on a random free port. +This is by design, to avoid port collisions that may arise with locally running software or in between parallel test runs.

+

Because there is this layer of indirection, it is necessary to ask Testcontainers for the actual mapped port at runtime. +This can be done using the getMappedPort method, which takes the original (container) port as an argument:

+ +

Retrieving actual ports at runtime inside_block:fetchPortsByNumber

+ + +
+

Warning +Because the randomised port mapping happens during container startup, the container must be running at the time getMappedPort is called. +You may need to ensure that the startup order of components in your tests caters for this.

+
+

There is also a getFirstMappedPort method for convenience, for the fairly common scenario of a container that only exposes one port:

+ +

Retrieving the first mapped port inside_block:fetchFirstMappedPort

+ + +

Getting the container host

+

When running with a local Docker daemon, exposed ports will usually be reachable on localhost. +However, in some CI environments they may instead be reachable on a different host.

+

As such, Testcontainers provides a convenience method to obtain an address on which the container should be reachable from the host machine.

+ +

Getting the container host inside_block:getHostOnly

+ + +

It is normally advisable to use getHost and getMappedPort together when constructing addresses - for example:

+ +

Getting the container host and mapped port inside_block:getHostAndMappedPort

+ + +
+

Tip +getHost() is a replacement for getContainerIpAddress() and returns the same result. +getContainerIpAddress() is believed to be confusingly named, and will eventually be deprecated.

+
+

Exposing host ports to the container

+

In some cases it is necessary to make a network connection from a container to a socket that is listening on the host machine. +Natively, Docker has limited support for this model across platforms. +Testcontainers, however, makes this possible.

+

In this example, assume that localServerPort is a port on our test host machine where a server (e.g. a web application) is running.

+

We need to tell Testcontainers to prepare to expose this port to containers:

+ +

Exposing the host port inside_block:exposePort

+ + +
+

Warning +Note that the above command should be invoked before containers are started, but after the server on the host was started.
Alternatively, use container.withAccessToHost(true) to force the host access mechanism (you still need to call exposeHostPorts to make the port available).

+
+

Having done so, we can now access this port from any containers that are launched. +From a container's perspective, the hostname will be host.testcontainers.internal and the port will be the same value as localServerPort.

+

For example, here we construct an HTTP URL for our local web application and tell a Selenium container to get a page from it:

+ +

Accessing the exposed host port from a container inside_block:useHostExposedPort

+ + + +

Advanced networking

+

Docker provides the ability for you to create custom networks and place containers on one or more networks. Then, communication can occur between networked containers without the need of exposing ports through the host. With Testcontainers, you can do this as well.

+
+

Warning +Note that Testcontainers currently only allows a container to be on a single network.

+
+ +

Creating custom networks inside_block:useCustomNetwork

+ +
\ No newline at end of file diff --git a/docs/sourcey/features/reuse.html b/docs/sourcey/features/reuse.html new file mode 100644 index 00000000000..999c8275ee2 --- /dev/null +++ b/docs/sourcey/features/reuse.html @@ -0,0 +1,62 @@ + +Reusable Containers (Experimental) - Testcontainers for Java Sourcey Reference
Core concepts

Reusable Containers (Experimental)

The Reusable feature keeps the containers running and next executions with the same container configuration will reuse it. To use it, start the container manually by calling start() method, do not call stop() method directly or indirectly via try-with-resources or JUnit integration, and enable it manually through an opt-in mechanism per environment. To reuse a container, the container configuration must be the same.
+

Warning +Reusable Containers is still an experimental feature and the behavior can change. +Those containers won't stop after all tests are finished.

+
+

The Reusable feature keeps the containers running and next executions with the same container configuration +will reuse it. To use it, start the container manually by calling start() method, do not call stop() method +directly or indirectly via try-with-resources or JUnit integration, and enable it manually through an +opt-in mechanism per environment. To reuse a container, the container configuration must be the same.

+
+

Note +Reusable containers are not suited for CI usage and as an experimental feature +not all Testcontainers features are fully working (e.g., resource cleanup +or networking).

+
+

How to use it

+
    +
  • Enable Reusable Containers
      +
    • through environment variable TESTCONTAINERS_REUSE_ENABLE=true
    • +
    • through user property file ~/.testcontainers.properties, by adding testcontainers.reuse.enable=true
    • +
    • not through classpath properties file see this comment
    • +
    +
  • +
  • Define a container and subscribe to reuse the container using withReuse(true)
  • +
+
+
+ +
+
GenericContainer container = new GenericContainer("redis:6-alpine")
+    .withExposedPorts(6379)
+    .withReuse(true)
+
    +
  • Start the container manually by using container.start()
  • +
+

Reusable Container with Testcontainers JDBC URL

+

If using the Testcontainers JDBC URL support +the URL must follow the pattern of jdbc:tc:mysql:8.0.36:///databasename?TC_REUSABLE=true. +TC_REUSABLE=true is set as a parameter of the JDBC URL.

+
\ No newline at end of file diff --git a/docs/sourcey/features/startup-and-waits.html b/docs/sourcey/features/startup-and-waits.html new file mode 100644 index 00000000000..67e36c7d8c2 --- /dev/null +++ b/docs/sourcey/features/startup-and-waits.html @@ -0,0 +1,119 @@ + +Waiting for containers to start or be ready - Testcontainers for Java Sourcey Reference
Core concepts

Waiting for containers to start or be ready

Ordinarily Testcontainers will wait for up to 60 seconds for the container's first mapped network port to start listening.
+

Wait strategies vs Startup strategies

+

Wait strategy: is the container in a state that is useful for testing. This is generally approximated as 'can we talk to this container over the network'. However, there are quite a few variations and nuances.

+

Startup strategy: did a container reach the desired running state. Almost always this just means 'wait until the container is running' - for a daemon process in a container this is the goal. Sometimes we need to wait until the container reaches a running state and then exits - this is the 'one shot startup' strategy, only used for cases where we need to run a one off command in a container but not a daemon.

+
+

Wait Strategies

+

Ordinarily Testcontainers will wait for up to 60 seconds for the container's first mapped network port to start listening.

+

This simple measure provides a basic check whether a container is ready for use.

+ +

Waiting for the first exposed port to start listening inside_block:waitForNetworkListening

+ + +

If the default 60s timeout is not sufficient, it can be altered with the withStartupTimeout() method.

+

If waiting for a listening TCP port is not sufficient to establish whether the container is ready, you can use the +waitingFor() method with other [WaitStrategy](http://static.javadoc.io/org.testcontainers/testcontainers/{{ latest_version }}/org/testcontainers/containers/wait/strategy/WaitStrategy.html) implementations as shown below.

+

HTTP Wait strategy examples

+

You can choose to wait for an HTTP(S) endpoint to return a particular status code.

+

Waiting for 200 OK

+ +

inside_block:waitForSimpleHttp

+ + +

Variations on the HTTP wait strategy are supported, including:

+

Waiting for multiple possible status codes

+ +

inside_block:waitForHttpWithMultipleStatusCodes

+ + +

Waiting for a status code that matches a predicate

+ +

Waiting for a status code that matches a predicate inside_block:waitForHttpWithStatusCodePredicate

+ + +

Using TLS

+ +

inside_block:waitForHttpWithTls

+ + +

Healthcheck Wait strategy examples

+

If the used image supports Docker's Healthcheck feature, you can directly leverage the healthy state of the container as your wait condition:

+ +

inside_block:healthcheckWait

+ + +

Log output Wait Strategy

+

In some situations a container's log output is a simple way to determine if it is ready or not. +For example, we can wait for a `Ready' message in the container's logs as follows:

+ +

inside_block:logMessageWait

+ + +

Other Wait Strategies

+

For further options, check out the [Wait](http://static.javadoc.io/org.testcontainers/testcontainers/{{ latest_version }}/org/testcontainers/containers/wait/strategy/Wait.html) convenience class, or the various subclasses of [WaitStrategy](http://static.javadoc.io/org.testcontainers/testcontainers/{{ latest_version }}/org/testcontainers/containers/wait/strategy/WaitStrategy.html).

+

If none of these options meet your requirements, you can create your own subclass of +[AbstractWaitStrategy](http://static.javadoc.io/org.testcontainers/testcontainers/{{ latest_version }}/org/testcontainers/containers/wait/strategy/AbstractWaitStrategy.html) with an +appropriate wait mechanism in waitUntilReady(). +The GenericContainer.waitingFor() method accepts any valid [WaitStrategy](http://static.javadoc.io/org.testcontainers/testcontainers/{{ latest_version }}/org/testcontainers/containers/wait/strategy/WaitStrategy.html).

+

Startup check Strategies

+

Ordinarily Testcontainers will check that the container has reached the running state and has not exited. +In order to do that inspect is executed against the container and state parameter is extracted.

+

All logic is implemented in [StartupCheckStrategy](http://static.javadoc.io/org.testcontainers/testcontainers/{{ latest_version }}/org/testcontainers/containers/startupcheck/StartupCheckStrategy.html) child classes.

+

Running startup strategy example

+

This is the strategy used by default. Testcontainers just checks if container is running.

+

Implemented in [IsRunningStartupCheckStrategy](http://static.javadoc.io/org.testcontainers/testcontainers/{{ latest_version }}/org/testcontainers/containers/startupcheck/IsRunningStartupCheckStrategy.html) class.

+

One shot startup strategy example

+

This strategy is intended for use with containers that only run briefly and exit of their own accord. As such, success is deemed to be when +the container has stopped with exit code 0.

+ +

Using one shot startup strategy inside_block:withOneShotStrategy

+ + +

Indefinite one shot startup strategy example

+

Variant of one shot strategy that does not impose a timeout. Intended for situation such as when a long running task forms part of + container startup.

+

It has to be assumed that the container will stop of its own accord, either with a success or failure exit code.

+ +

Using indefinite one shot startup strategy inside_block:withIndefiniteOneShotStrategy

+ + +

Minimum duration startup strategy example

+

Checks that the container is running and has been running for a defined minimum period of time.

+ +

Using minimum duration strategy inside_block:withMinimumDurationStrategy

+ + +

Other startup strategies

+

If none of these options meet your requirements, you can create your own subclass of +[StartupCheckStrategy](http://static.javadoc.io/org.testcontainers/testcontainers/{{ latest_version }}/org/testcontainers/containers +/startupcheck/StartupCheckStrategy.html) with an appropriate startup check mechanism in waitUntilStartupSuccessful(). +Or you can leave it as is and just implement the checkStartupState(DockerClient dockerClient, String containerId) if you still want to check state + periodically.

+

Depending on another container

+

Sometimes, a container relies on another container to be ready before it should start itself. An example of this might be a database that needs to be started before your application container can link to it. You can tell a container that it depends on another container by using the dependsOn method:

+ +

Depending on another container inside_block:dependsOn

+ +
\ No newline at end of file diff --git a/docs/sourcey/icons/github.svg b/docs/sourcey/icons/github.svg new file mode 100644 index 00000000000..d563c83aa0a --- /dev/null +++ b/docs/sourcey/icons/github.svg @@ -0,0 +1,4 @@ + + + \ No newline at end of file diff --git a/docs/sourcey/icons/slack.svg b/docs/sourcey/icons/slack.svg new file mode 100644 index 00000000000..942265e1d23 --- /dev/null +++ b/docs/sourcey/icons/slack.svg @@ -0,0 +1,10 @@ + + + + + + \ No newline at end of file diff --git a/docs/sourcey/icons/stackoverflow.svg b/docs/sourcey/icons/stackoverflow.svg new file mode 100644 index 00000000000..c3307627c4e --- /dev/null +++ b/docs/sourcey/icons/stackoverflow.svg @@ -0,0 +1,5 @@ + + + + \ No newline at end of file diff --git a/docs/sourcey/icons/twitter.svg b/docs/sourcey/icons/twitter.svg new file mode 100644 index 00000000000..ef3fbc6217e --- /dev/null +++ b/docs/sourcey/icons/twitter.svg @@ -0,0 +1,4 @@ + + + \ No newline at end of file diff --git a/docs/sourcey/index.html b/docs/sourcey/index.html new file mode 100644 index 00000000000..e749ae96d53 --- /dev/null +++ b/docs/sourcey/index.html @@ -0,0 +1,247 @@ + +Testcontainers for Java - Testcontainers for Java Sourcey Reference
Pages

Testcontainers for Java

Testcontainers for Java is a Java library that supports JUnit tests, providing lightweight, throwaway instances of common databases, Selenium web browsers, or anything else that can run in a Docker container.

Not using Java? Here are other supported languages!

+
+ Java + Go + .NET + Node.js + Python + Rust + Haskell + Ruby +
+ +

About Testcontainers for Java

+

Testcontainers for Java is a Java library that supports JUnit tests, providing lightweight, throwaway instances of common databases, Selenium web browsers, or anything else that can run in a Docker container.

+

Testcontainers make the following kinds of tests easier:

+
    +
  • Data access layer integration tests: use a containerized instance of a MySQL, PostgreSQL or Oracle database to test your data access layer code for complete compatibility, but without requiring complex setup on developers' machines and safe in the knowledge that your tests will always start with a known DB state. Any other database type that can be containerized can also be used.
  • +
  • Application integration tests: for running your application in a short-lived test mode with dependencies, such as databases, message queues or web servers.
  • +
  • UI/Acceptance tests: use containerized web browsers, compatible with Selenium, for conducting automated UI tests. Each test can get a fresh instance of the browser, with no browser state, plugin variations or automated browser upgrades to worry about. And you get a video recording of each test session, or just each session where tests failed.
  • +
  • Much more! Check out the various contributed modules or create your own custom container classes using GenericContainer as a base.
  • +
+

Prerequisites

+ +

Maven dependencies

+

Testcontainers is distributed as separate JARs with a common version number:

+
    +
  • A core JAR file for core functionality, generic containers and docker-compose support
  • +
  • A separate JAR file for each of the specialised modules. Each module's documentation describes the Maven/Gradle dependency to add to your project's build.
  • +
+

For the core library, the latest Maven/Gradle dependency is as follows:

+

Gradle

+
+
+ +
+
testImplementation "org.testcontainers:testcontainers:{{latest_version}}"
+

Maven

+
+
+ +
+
&lt;dependency&gt;
+    &lt;groupId&gt;org.testcontainers</groupId>
+    &lt;artifactId&gt;testcontainers</artifactId>
+    &lt;version&gt;{{latest_version}}</version>
+    &lt;scope&gt;test</scope>
+</dependency>
+

You can also check the latest version available on Maven Central.

+

Managing versions for multiple Testcontainers dependencies

+

To avoid specifying the version of each dependency, you can use a BOM or Bill Of Materials.

+

Using Maven you can add the following to dependencyManagement section in your pom.xml: +Maven

+
+
+ +
+
&lt;dependencyManagement&gt;
+    &lt;dependencies&gt;
+        &lt;dependency&gt;
+            &lt;groupId&gt;org.testcontainers</groupId>
+            &lt;artifactId&gt;testcontainers-bom</artifactId>
+            &lt;version&gt;{{latest_version}}</version>
+            &lt;type&gt;pom</type>
+            &lt;scope&gt;import</scope>
+        </dependency>
+    </dependencies>
+</dependencyManagement>
+

and then use dependencies without specifying a version: +Maven

+
+
+ +
+
&lt;dependency&gt;
+    &lt;groupId&gt;org.testcontainers</groupId>
+    &lt;artifactId&gt;testcontainers-mysql</artifactId>
+    &lt;scope&gt;test</scope>
+</dependency>
+

Using Gradle 5.0 or higher, you can add the following to the dependencies section in your build.gradle:

+

Gradle

+
+
+ +
+
implementation platform('org.testcontainers:testcontainers-bom:{{latest_version}}') //import bom
+testImplementation('org.testcontainers:testcontainers-mysql') //no version specified
+

JitPack builds are available for pre-release versions.

+
+

Shaded dependencies +Testcontainers depends on other libraries (like docker-java) for it to work.
Some of them (JUnit, docker-java-{api,transport} and its transitive dependencies, JNA, visible-assertions and others) are part of our public API.
But there are also "private", implementation detail dependencies (e.g., docker-java-core, Guava, OkHttp, etc.) that are not exposed to public API but prone to conflicts with test code/application under test code. +As such, these libraries are 'shaded' into the core Testcontainers JAR and relocated under org.testcontainers.shaded to prevent class conflicts.

+
+

Sponsors

+

A huge thank you to our sponsors:

+

Bronze sponsors

+ + + + + + + + + + +

Donors

+ + + + +

Backers

+ +

Who is using Testcontainers?

+
    +
  • ZeroTurnaround - Testing of the Java Agents, micro-services, Selenium browser automation
  • +
  • Zipkin - MySQL and Cassandra testing
  • +
  • Apache Gora - CouchDB testing
  • +
  • Apache James - LDAP and Cassandra integration testing
  • +
  • StreamSets - LDAP, MySQL Vault, MongoDB, Redis integration testing
  • +
  • Playtika - Kafka, Couchbase, MariaDB, Redis, Neo4j, Aerospike, MemSQL
  • +
  • JetBrains - Testing of the TeamCity plugin for HashiCorp Vault
  • +
  • Plumbr - Integration testing of data processing pipeline micro-services
  • +
  • Streamlio - Integration and Chaos Testing of our fast data platform based on Apache Pulsar, Apache BookKeeper and Apache Heron.
  • +
  • Spring Session - Redis, PostgreSQL, MySQL and MariaDB integration testing
  • +
  • Apache Camel - Testing Camel against native services such as Consul, Etcd and so on
  • +
  • Infinispan - Testing the Infinispan Server as well as integration tests with databases, LDAP and KeyCloak
  • +
  • Instana - Testing agents and stream processing backends
  • +
  • eBay Marketing - Testing for MySQL, Cassandra, Redis, Couchbase, Kafka, etc.
  • +
  • Skyscanner - Integration testing against HTTP service mocks and various data stores
  • +
  • Neo4j-OGM - Testing with Neo4j
  • +
  • Spring Data Neo4j - Testing imperative and reactive implementations with Neo4j
  • +
  • Lightbend - Testing Alpakka Kafka and support in Alpakka Kafka Testkit
  • +
  • Zalando SE - Testing core business services
  • +
  • Europace AG - Integration testing for databases and micro services
  • +
  • Micronaut Data - Testing of Micronaut Data JDBC, a database access toolkit
  • +
  • Vert.x SQL Client - Testing with PostgreSQL, MySQL, MariaDB, SQL Server, etc.
  • +
  • JHipster - Couchbase and Cassandra integration testing
  • +
  • wescale - Integration testing against HTTP service mocks and various data stores
  • +
  • Marquez - PostgreSQL integration testing
  • +
  • Wise (formerly TransferWise) - Integration testing for different RDBMS, kafka and micro services
  • +
  • XWiki - Testing XWiki under all supported configurations
  • +
  • Apache SkyWalking - End-to-end testing of the Apache SkyWalking, and plugin tests of its subproject, Apache SkyWalking Python, and of its eco-system built by the community, like SkyAPM NodeJS Agent
  • +
  • jOOQ - Integration testing all of jOOQ with a variety of RDBMS
  • +
  • Trino (formerly Presto SQL) - Integration testing all Trino core & connectors, including tests of multi-node deployments and security configurations.
  • +
  • Google - Various open source projects: OpenTelemetry, Universal Application Tool, CloudBowl
  • +
  • Backbase - Unit, Integration and Acceptance testing for different the databases supported (Oracle, SQL Server, MySQL), the different messaging systems supported (Kafka, Rabbit, AMQ) and other microservices and HTTP mocks.
  • +
  • CloudBees - Integration testing of products, including but not limited to database and AWS/Localstack integration testing.
  • +
  • Jenkins - Integration testing of multiple plugins and the Trilead SSH2 fork maintained by the Jenkins community +(query).
  • +
  • Elastic - Integration testing of the Java APM agent
  • +
  • Alkira - Testing of multiple micro-services using Kafka, PostgreSQL, Apache Zookeeper, Etcd and so on.
  • +
  • Togglz - Feature Flags for the Java platform
  • +
  • Byzer - Integration tests for Data and AI platforms are based on multiple versions of Byzer, Ray and Apache Spark.
  • +
  • Apache SeaTunnel - Integration testing with different datasource.
  • +
  • Bucket4j - Java rate-limiting library based on the token-bucket algorithm.
  • +
  • Spark ClickHouse Connector - Integration tests for Apache Spark with both single node ClickHouse instance and multi-node ClickHouse cluster.
  • +
  • Quarkus - Testcontainers is used extensively for Quarkus' DevServices feature.
  • +
  • Apache Kyuubi - Integration testing with Trino as data source engine, Kafka, etc.
  • +
  • Dash0 - Integration testing for OpenTelemetry Observability product.
  • +
+

License

+

See LICENSE.

+

Attributions

+

This project includes a modified class (ScriptUtils) taken from the Spring JDBC project, adapted under the terms of the Apache license. Copyright for that class remains with the original authors.

+

This project was initially inspired by a gist by Moshe Eshel.

+ +

Copyright (c) 2015-2021 Richard North and other authors.

+

See AUTHORS for contributors.

+
\ No newline at end of file diff --git a/docs/sourcey/js/tc-header.js b/docs/sourcey/js/tc-header.js new file mode 100644 index 00000000000..4186b6ca59b --- /dev/null +++ b/docs/sourcey/js/tc-header.js @@ -0,0 +1,45 @@ +const mobileToggle = document.getElementById("mobile-menu-toggle"); +const mobileSubToggle = document.getElementById("mobile-submenu-toggle"); +function toggleMobileMenu() { + document.body.classList.toggle('mobile-menu'); + document.body.classList.toggle("mobile-tc-header-active"); +} +function toggleMobileSubmenu() { + document.body.classList.toggle('mobile-submenu'); +} +if (mobileToggle) + mobileToggle.addEventListener("click", toggleMobileMenu); +if (mobileSubToggle) + mobileSubToggle.addEventListener("click", toggleMobileSubmenu); + +const allParentMenuItems = document.querySelectorAll("#site-header .menu-item.has-children"); +function clearActiveMenuItem() { + document.body.classList.remove("tc-header-active"); + allParentMenuItems.forEach((item) => { + item.classList.remove("active"); + }); +} +function setActiveMenuItem(e) { + clearActiveMenuItem(); + e.currentTarget.closest(".menu-item").classList.add("active"); + document.body.classList.add("tc-header-active"); +} +allParentMenuItems.forEach((item) => { + const trigger = item.querySelector(":scope > a, :scope > button"); + + trigger.addEventListener("click", (e) => { + if (e.currentTarget.closest(".menu-item").classList.contains("active")) { + clearActiveMenuItem(); + } else { + setActiveMenuItem(e); + } + }); + + trigger.addEventListener("mouseenter", (e) => { + setActiveMenuItem(e); + }); + + item.addEventListener("mouseleave", (e) => { + clearActiveMenuItem(); + }); +}); \ No newline at end of file diff --git a/docs/sourcey/language-logos/dotnet.svg b/docs/sourcey/language-logos/dotnet.svg new file mode 100644 index 00000000000..2fb163d4d40 --- /dev/null +++ b/docs/sourcey/language-logos/dotnet.svg @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/docs/sourcey/language-logos/go.svg b/docs/sourcey/language-logos/go.svg new file mode 100644 index 00000000000..bfcca48ceda --- /dev/null +++ b/docs/sourcey/language-logos/go.svg @@ -0,0 +1,10 @@ + + + + + + + \ No newline at end of file diff --git a/docs/sourcey/language-logos/haskell.svg b/docs/sourcey/language-logos/haskell.svg new file mode 100644 index 00000000000..eb6de3776ec --- /dev/null +++ b/docs/sourcey/language-logos/haskell.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/docs/sourcey/language-logos/java.svg b/docs/sourcey/language-logos/java.svg new file mode 100644 index 00000000000..590da12d96a --- /dev/null +++ b/docs/sourcey/language-logos/java.svg @@ -0,0 +1,17 @@ + + + + + + + + + \ No newline at end of file diff --git a/docs/sourcey/language-logos/nodejs.svg b/docs/sourcey/language-logos/nodejs.svg new file mode 100644 index 00000000000..08c6ea7bdd4 --- /dev/null +++ b/docs/sourcey/language-logos/nodejs.svg @@ -0,0 +1,5 @@ + + + \ No newline at end of file diff --git a/docs/sourcey/language-logos/python.svg b/docs/sourcey/language-logos/python.svg new file mode 100644 index 00000000000..d06a313c96b --- /dev/null +++ b/docs/sourcey/language-logos/python.svg @@ -0,0 +1,8 @@ + + + + \ No newline at end of file diff --git a/docs/sourcey/language-logos/ruby.svg b/docs/sourcey/language-logos/ruby.svg new file mode 100644 index 00000000000..05537cedf72 --- /dev/null +++ b/docs/sourcey/language-logos/ruby.svg @@ -0,0 +1,125 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/sourcey/language-logos/rust.svg b/docs/sourcey/language-logos/rust.svg new file mode 100644 index 00000000000..89039333533 --- /dev/null +++ b/docs/sourcey/language-logos/rust.svg @@ -0,0 +1,57 @@ + + + \ No newline at end of file diff --git a/docs/sourcey/llms-full.txt b/docs/sourcey/llms-full.txt new file mode 100644 index 00000000000..136609c6b34 --- /dev/null +++ b/docs/sourcey/llms-full.txt @@ -0,0 +1,205 @@ +# Testcontainers for Java Sourcey Reference + +*Testcontainers for Java* is a Java library that supports JUnit tests, providing lightweight, throwaway instances of common databases, Selenium web browsers, or anything else that can run in a Docker container. + +## Java Guide + +### Testcontainers for Java + +Path: `/sourcey/` + +*Testcontainers for Java* is a Java library that supports JUnit tests, providing lightweight, throwaway instances of common databases, Selenium web browsers, or anything else that can run in a Docker container. + +Not using Java? Here are other supported languages! Java Go .NET Node.js Python Rust Haskell Ruby About Testcontainers for Java Testcontainers for Java is a Java library that supports JUnit tests, providing lightweight, throwaway instances of common databases, Selenium web browsers, or anything else that can run in a Docker container. Testcontainers make the following kinds of tests easier: Data access layer integration tests : use a containerized instance of a MySQL, PostgreSQL or Oracle database to test your data access layer code for complete compatibility, but without requiring complex setup on developers' machines and safe in the knowledge that your tests will always start with a known DB state. Any other database type that can be containerized can also be used. Application integration tests : for running your application in a short-lived test mode with dependencies, such as databases, message queues or web servers. UI/Acceptance tests : use containerized web browsers , compatible with Selenium, for conducting automated UI tests. Each test can get a fresh instance of the browser, with no browser state, plugin variations or automated browser upgrades to worry about. And you get a video recording of each test session, or just each session where tests failed. Much more! Check out the various contributed modules or create your own custom container classes using GenericContainer as a base. Prerequisites Docker - please see General Docker requirements A supported JVM testing framework: JUnit 4 - See the JUnit 4 Quickstart Guide Jupiter/JUnit 5 Spock Or manually add code to control the container/test lifecycle (See hints for this approach ) Maven dependencies Testcontainers is distributed as separate JARs with a common version number: A core JAR file for core functionality, generic containers and docker-compose support A separate JAR file for each of the specialised modules. Each module's documentation describes the Maven/Gradle dependency to add to your project's build. For the core library, the latest Maven/Gradle dependency is as follows: Gradle Copy testImplementation "org.testcontainers:testcontainers:{{latest_version}}" Maven Copy dependency > groupId > org.testcontainers groupId > artifactId > testcontainers artifactId > version > {{latest_version}} version > scope > test scope > dependency > You can also check the latest version available on Maven Central . Managing versions for multiple Testcontainers dependencies To avoid specifying the version of each dependency, you can use a BOM or Bill Of Materials . Using Maven you can add the following to dependencyManagement section in your pom.xml : Maven Copy dependencyManagement > dependencies > dependency > groupId > org.testcontainers groupId > artifactId > testcontainers-bom artifactId > version > {{latest_version}} version > type > pom type > scope > import scope > dependency > dependencies > dependencyManagement > and then use dependencies without specifying a version: Maven Copy dependency > groupId > org.testcontainers groupId > artifactId > testcontainers-mysql artifactId > scope > test scope > dependency > Using Gradle 5.0 or higher, you can add the following to the dependencies section in your build.gradle : Gradle Copy implementation platform('org.testcontainers:testcontainers-bom:{{latest_version}}') //import bom testImplementation('org.testcontainers:testcontainers-mysql') //no version specified JitPack builds are available for pre-release versions. Shaded dependencies Testcontainers depends on other libraries (like docker-java) for it to work. Some of them (JUnit, docker-java-{api,transport} and its transitive dependencies, JNA, visible-assertions and others) are part of our public API. But there are also "private", implementation detail dependencies (e.g., docker-java-core, Guava, OkHttp, etc.) that are not exposed to public API but prone to conflicts with test code/application under test code. As such, these libraries are 'shaded' into the core Testcontainers JAR and relocated under org.testcontainers.shaded to prevent class conflicts. Sponsors A huge thank you to our sponsors: Bronze sponsors Cirrus CI Vivy jOOQ Backbase Elastic Donors Red Hat Spotify Backers Philip Riecks (@rieckpil) Karl Heinz Marbaise (@khmarbaise) Sascha Frinken (@sascha-frinken) Christoph Dreis (@dreis2211) Nikita Zhevnitskiy (@zhenik) Bas Stoker (@bastoker) Oleg Nenashev (@oleg-nenashev) Rik Glover (@rikglover) Amitosh Swain Mahapatra (@recrsn) Paris Apostolopoulos Who is using Testcontainers? ZeroTurnaround - Testing of the Java Agents, micro-services, Selenium browser automation Zipkin - MySQL and Cassandra testing Apache Gora - CouchDB testing Apache James - LDAP and Cassandra integration testing StreamSets - LDAP, MySQL Vault, MongoDB, Redis integration testing Playtika - Kafka, Couchbase, MariaDB, Redis, Neo4j, Aerospike, MemSQL JetBrains - Testing of the TeamCity plugin for HashiCorp Vault Plumbr - Integration testing of data processing pipeline micro-services Streamlio - Integration and Chaos Testing of our fast data platform based on Apache Pulsar, Apache BookKeeper and Apache Heron. Spring Session - Redis, PostgreSQL, MySQL and MariaDB integration testing Apache Camel - Testing Camel against native services such as Consul, Etcd and so on Infinispan - Testing the Infinispan Server as well as integration tests with databases, LDAP and KeyCloak Instana - Testing agents and stream processing backends eBay Marketing - Testing for MySQL, Cassandra, Redis, Couchbase, Kafka, etc. Skyscanner - Integration testing against HTTP service mocks and various data stores Neo4j-OGM - Testing with Neo4j Spring Data Neo4j - Testing imperative and reactive implementations with Neo4j Lightbend - Testing Alpakka Kafka and support in Alpakka Kafka Testkit Zalando SE - Testing core business services Europace AG - Integration testing for databases and micro services Micronaut Data - Testing of Micronaut Data JDBC, a database access toolkit Vert.x SQL Client - Testing with PostgreSQL, MySQL, MariaDB, SQL Server, etc. JHipster - Couchbase and Cassandra integration testing wescale - Integration testing against HTTP service mocks and various data stores Marquez - PostgreSQL integration testing Wise (formerly TransferWise) - Integration testing for different RDBMS, kafka and micro services XWiki - Testing XWiki under all supported configurations Apache SkyWalking - End-to-end testing of the Apache SkyWalking, and plugin tests of its subproject, Apache SkyWalking Python , and of its eco-system built by the community, like SkyAPM NodeJS Agent jOOQ - Integration testing all of jOOQ with a variety of RDBMS Trino (formerly Presto SQL) - Integration testing all Trino core & connectors, including tests of multi-node deployments and security configurations. Google - Various open source projects: OpenTelemetry , Universal Application Tool , CloudBowl Backbase - Unit, Integration and Acceptance testing for different the databases supported (Oracle, SQL Server, MySQL), the different messaging systems supported (Kafka, Rabbit, AMQ) and other microservices and HTTP mocks. CloudBees - Integration testing of products, including but not limited to database and AWS/Localstack integration testing. Jenkins - Integration testing of multiple plugins and the Trilead SSH2 fork maintained by the Jenkins community ( query ). Elastic - Integration testing of the Java APM agent Alkira - Testing of multiple micro-services using Kafka, PostgreSQL, Apache Zookeeper, Etcd and so on. Togglz - Feature Flags for the Java platform Byzer - Integration tests for Data and AI platforms are based on multiple versions of Byzer, Ray and Apache Spark. Apache SeaTunnel - Integration testing with different datasource. Bucket4j - Java rate-limiting library based on the token-bucket algorithm. Spark ClickHouse Connector - Integration tests for Apache Spark with both single node ClickHouse instance and multi-node ClickHouse cluster. Quarkus - Testcontainers is used extensively for Quarkus' DevServices feature. Apache Kyuubi - Integration testing with Trino as data source engine, Kafka, etc. Dash0 - Integration testing for OpenTelemetry Observability product. License See LICENSE . Attributions This project includes a modified class (ScriptUtils) taken from the Spring JDBC project, adapted under the terms of the Apache license. Copyright for that class remains with the original authors. This project was initially inspired by a gist by Moshe Eshel . Copyright Copyright (c) 2015-2021 Richard North and other authors. See AUTHORS for contributors. + +### Examples + +Path: `/sourcey/examples.html` + +Examples of different use cases provided by Testcontainers can be found below: + +Examples of different use cases provided by Testcontainers can be found below: Hazelcast Kafka Cluster with multiple brokers Neo4j Redis Selenium Selenium Module with Cucumber Singleton Container Pattern Solr Spring Boot Spring Boot with Kotlin TestNG ImmuDb Zookeeper NATS SFTP + +### JUnit 4 Quickstart + +Path: `/sourcey/quickstart/junit-4-quickstart.html` + +It's easy to add Testcontainers to your project - let's walk through a quick example to see how. + +It's easy to add Testcontainers to your project - let's walk through a quick example to see how. Let's imagine we have a simple program that has a dependency on Redis, and we want to add some tests for it. In our imaginary program, there is a RedisBackedCache class which stores data in Redis. You can see an example test that could have been written for it (without using Testcontainers): Pre-Testcontainers test code block:RedisBackedCacheIntTestStep0 Notice that the existing test has a problem - it's relying on a local installation of Redis, which is a red flag for test reliability. This may work if we were sure that every developer and CI machine had Redis installed, but would fail otherwise. We might also have problems if we attempted to run tests in parallel, such as state bleeding between tests, or port clashes. Let's start from here, and see how to improve the test with Testcontainers: 1. Add Testcontainers as a test-scoped dependency First, add Testcontainers as a dependency as follows: Gradle Copy testImplementation "org.testcontainers:testcontainers:{{latest_version}}" Maven Copy dependency > groupId > org.testcontainers groupId > artifactId > testcontainers artifactId > version > {{latest_version}} version > scope > test scope > dependency > 2. Get Testcontainers to run a Redis container during our tests Simply add the following to the body of our test class: JUnit 4 Rule inside_block:rule The @Rule annotation tells JUnit to notify this field about various events in the test lifecycle. In this case, our rule object is a Testcontainers GenericContainer , configured to use a specific Redis image from Docker Hub, and configured to expose a port. If we run our test as-is, then regardless of the actual test outcome, we'll see logs showing us that Testcontainers: was activated before our test method ran discovered and quickly tested our local Docker setup pulled the image if necessary started a new container and waited for it to be ready shut down and deleted the container after the test 3. Make sure our code can talk to the container Before Testcontainers, we might have hardcoded an address like localhost:6379 into our tests. Testcontainers uses randomized ports for each container it starts, but makes it easy to obtain the actual port at runtime. We can do this in our test setUp method, to set up our component under test: Obtaining a mapped port inside_block:setUp Tip Notice that we also ask Testcontainers for the container's actual address with redis.getHost(); , rather than hard-coding localhost . localhost may work in some environments but not others - for example it may not work on your current or future CI environment. As such, avoid hard-coding the address, and use getHost() instead. 4. Run the tests! That's it! Let's look at our complete test class to see how little we had to add to get up and running with Testcontainers: RedisBackedCacheIntTest block:RedisBackedCacheIntTest + +### JUnit 5 Quickstart + +Path: `/sourcey/quickstart/junit-5-quickstart.html` + +It's easy to add Testcontainers to your project - let's walk through a quick example to see how. + +It's easy to add Testcontainers to your project - let's walk through a quick example to see how. Let's imagine we have a simple program that has a dependency on Redis, and we want to add some tests for it. In our imaginary program, there is a RedisBackedCache class which stores data in Redis. You can see an example test that could have been written for it (without using Testcontainers): Pre-Testcontainers test code block:RedisBackedCacheIntTestStep0 Notice that the existing test has a problem - it's relying on a local installation of Redis, which is a red flag for test reliability. This may work if we were sure that every developer and CI machine had Redis installed, but would fail otherwise. We might also have problems if we attempted to run tests in parallel, such as state bleeding between tests, or port clashes. Let's start from here, and see how to improve the test with Testcontainers: 1. Add Testcontainers as a test-scoped dependency First, add Testcontainers as a dependency as follows: Gradle Copy testImplementation "org.junit.jupiter:junit-jupiter:5.8.1" testImplementation "org.testcontainers:testcontainers:{{latest_version}}" testImplementation "org.testcontainers:testcontainers-junit-jupiter:{{latest_version}}" Maven Copy dependency > groupId > org.junit.jupiter groupId > artifactId > junit-jupiter artifactId > version > 5.8.1 version > scope > test scope > dependency > dependency > groupId > org.testcontainers groupId > artifactId > testcontainers artifactId > version > {{latest_version}} version > scope > test scope > dependency > dependency > groupId > org.testcontainers groupId > artifactId > testcontainers-junit-jupiter artifactId > version > {{latest_version}} version > scope > test scope > dependency > 2. Get Testcontainers to run a Redis container during our tests First, you'll need to annotate the test class with @Testcontainers . Furthermore, add the following to the body of our test class: JUnit 5 Rule inside_block:container The @Container annotation tells JUnit to notify this field about various events in the test lifecycle. In this case, our rule object is a Testcontainers GenericContainer , configured to use a specific Redis image from Docker Hub, and configured to expose a port. If we run our test as-is, then regardless of the actual test outcome, we'll see logs showing us that Testcontainers: was activated before our test method ran discovered and quickly tested our local Docker setup pulled the image if necessary started a new container and waited for it to be ready shut down and deleted the container after the test 3. Make sure our code can talk to the container Before Testcontainers, we might have hardcoded an address like localhost:6379 into our tests. Testcontainers uses randomized ports for each container it starts, but makes it easy to obtain the actual port at runtime. We can do this in our test setUp method, to set up our component under test: Obtaining a mapped port inside_block:setUp Tip Notice that we also ask Testcontainers for the container's actual address with redis.getHost(); , rather than hard-coding localhost . localhost may work in some environments but not others - for example it may not work on your current or future CI environment. As such, avoid hard-coding the address, and use getHost() instead. 4. Additional attributes Additional attributes are available for the @Testcontainers annotation. Those attributes can be helpful when: Tests should be skipped instead of failing because Docker is unavailable in the current environment. Set disabledWithoutDocker to true . Enable parallel container initialization instead of sequential (by default). Set parallel to true . 5. Run the tests! That's it! Let's look at our complete test class to see how little we had to add to get up and running with Testcontainers: RedisBackedCacheIntTest inside_block:class + +### Spock Quickstart + +Path: `/sourcey/quickstart/spock-quickstart.html` + +It's easy to add Testcontainers to your project - let's walk through a quick example to see how. + +It's easy to add Testcontainers to your project - let's walk through a quick example to see how. Let's imagine we have a simple program that has a dependency on Redis, and we want to add some tests for it. In our imaginary program, there is a RedisBackedCache class which stores data in Redis. You can see an example test that could have been written for it (without using Testcontainers): Pre-Testcontainers test code block:RedisBackedCacheIntTestStep0 Notice that the existing test has a problem - it's relying on a local installation of Redis, which is a red flag for test reliability. This may work if we were sure that every developer and CI machine had Redis installed, but would fail otherwise. We might also have problems if we attempted to run tests in parallel, such as state bleeding between tests, or port clashes. Let's start from here, and see how to improve the test with Testcontainers: 1. Add Testcontainers as a test-scoped dependency First, add Testcontainers as a dependency as follows: Gradle Copy testImplementation "org.testcontainers:testcontainers-spock:{{latest_version}}" Maven Copy dependency > groupId > org.testcontainers groupId > artifactId > testcontainers-spock artifactId > version > {{latest_version}} version > scope > test scope > dependency > 2. Get Testcontainers to run a Redis container during our tests Annotate the Spock specification class with the Testcontainers extension: Spock Testcontainers annotation Copy @org.testcontainers.spock.Testcontainers class RedisBackedCacheIntTest extends Specification { And add the following field to the body of our test class: Spock Testcontainers init inside_block:init This tells Spock to start a Testcontainers GenericContainer , configured to use a specific Redis image from Docker Hub, and configured to expose a port. If we run our test as-is, then regardless of the actual test outcome, we'll see logs showing us that Testcontainers: was activated before our test method ran discovered and quickly tested our local Docker setup pulled the image if necessary started a new container and waited for it to be ready shut down and deleted the container after the test 3. Make sure our code can talk to the container Before Testcontainers, we might have hardcoded an address like localhost:6379 into our tests. Testcontainers uses randomized ports for each container it starts, but makes it easy to obtain the actual port at runtime. We can do this in our test setup method, to set up our component under test: Obtaining a mapped port inside_block:setup Tip Notice that we also ask Testcontainers for the container's actual address with redis.containerIpAddress , rather than hard-coding localhost . localhost may work in some environments but not others - for example it may not work on your current or future CI environment. As such, avoid hard-coding the address, and use containerIpAddress instead. 4. Run the tests! That's it! Let's look at our complete test class to see how little we had to add to get up and running with Testcontainers: RedisBackedCacheIntTest block:complete + +### Creating a container + +Path: `/sourcey/features/creating-container.html` + +Testcontainers' generic container support offers the most flexibility, and makes it easy to use virtually any container images as temporary test dependencies. For example, if you might use it to test interactions with: + +Creating a generic container based on an image Testcontainers' generic container support offers the most flexibility, and makes it easy to use virtually any container images as temporary test dependencies. For example, if you might use it to test interactions with: NoSQL databases or other data stores (e.g. redis, elasticsearch, mongo) Web servers/proxies (e.g. nginx, apache) Log services (e.g. logstash, kibana) Other services developed by your team/organization which are already dockerized With a generic container, you set the container image using a parameter to the rule constructor, e.g.: Copy new GenericContainer ( DockerImageName . parse ( "jboss/wildfly:9.0.1.Final" )) Specifying an image Many Container classes in Testcontainers have historically supported: a no-args constructor - for example new GenericContainer() and new ElasticsearchContainer() . With these constructors, Testcontainers has traditionally used a default image name (including a fixed image tag/version). This has caused a conflict between the need to keep the defaults sane (i.e. up to date) and the need to avoid silently upgrading these dependencies along with new versions of Testcontainers. a single string-argument constructor, which has taken either a version or an image name as a String. This has caused some ambiguity and confusion. Since v1.15.0, both of these constructor types have been deprecated, for the reasons given above. Instead, it is highly recommended that all containers be constructed using a constructor that accepts a DockerImageName object. The DockerImageName class is an unambiguous reference to a docker image. It is suggested that developers treat DockerImageName s as you would any other potentially-constant value - consider defining a constant in your test codebase that matches the production version of the dependency you are using. Examples A generic container rule can be used with any public docker image; for example: Creating a Redis container inside_block:container The container, as @Container , will be started before any tests in the class run, and will be destroyed after all tests have run. + +### Networking and communicating with containers + +Path: `/sourcey/features/networking.html` + +It is common to want to connect to a container from your test process, running on the test 'host' machine. For example, you may be testing a class that needs to connect to a backend or data store container. + +Exposing container ports to the host It is common to want to connect to a container from your test process, running on the test 'host' machine. For example, you may be testing a class that needs to connect to a backend or data store container. Generally, each required port needs to be explicitly exposed. For example, we can specify one or more ports as follows: Exposing ports inside_block:rule Note that this exposed port number is from the perspective of the container . From the host's perspective Testcontainers actually exposes this on a random free port. This is by design, to avoid port collisions that may arise with locally running software or in between parallel test runs. Because there is this layer of indirection, it is necessary to ask Testcontainers for the actual mapped port at runtime. This can be done using the getMappedPort method, which takes the original (container) port as an argument: Retrieving actual ports at runtime inside_block:fetchPortsByNumber Warning Because the randomised port mapping happens during container startup, the container must be running at the time getMappedPort is called. You may need to ensure that the startup order of components in your tests caters for this. There is also a getFirstMappedPort method for convenience, for the fairly common scenario of a container that only exposes one port: Retrieving the first mapped port inside_block:fetchFirstMappedPort Getting the container host When running with a local Docker daemon, exposed ports will usually be reachable on localhost . However, in some CI environments they may instead be reachable on a different host. As such, Testcontainers provides a convenience method to obtain an address on which the container should be reachable from the host machine. Getting the container host inside_block:getHostOnly It is normally advisable to use getHost and getMappedPort together when constructing addresses - for example: Getting the container host and mapped port inside_block:getHostAndMappedPort Tip getHost() is a replacement for getContainerIpAddress() and returns the same result. getContainerIpAddress() is believed to be confusingly named, and will eventually be deprecated. Exposing host ports to the container In some cases it is necessary to make a network connection from a container to a socket that is listening on the host machine. Natively, Docker has limited support for this model across platforms. Testcontainers, however, makes this possible. In this example, assume that localServerPort is a port on our test host machine where a server (e.g. a web application) is running. We need to tell Testcontainers to prepare to expose this port to containers: Exposing the host port inside_block:exposePort Warning Note that the above command should be invoked before containers are started, but after the server on the host was started. Alternatively, use container.withAccessToHost(true) to force the host access mechanism (you still need to call exposeHostPorts to make the port available). Having done so, we can now access this port from any containers that are launched. From a container's perspective, the hostname will be host.testcontainers.internal and the port will be the same value as localServerPort . For example, here we construct an HTTP URL for our local web application and tell a Selenium container to get a page from it: Accessing the exposed host port from a container inside_block:useHostExposedPort Advanced networking Docker provides the ability for you to create custom networks and place containers on one or more networks. Then, communication can occur between networked containers without the need of exposing ports through the host. With Testcontainers, you can do this as well. Warning Note that Testcontainers currently only allows a container to be on a single network. Creating custom networks inside_block:useCustomNetwork + +### Executing commands + +Path: `/sourcey/features/commands.html` + +By default the container will execute whatever command is specified in the image's Dockerfile. To override this, and specify a different command, use `withCommand`. For example: + +Container startup command By default the container will execute whatever command is specified in the image's Dockerfile. To override this, and specify a different command, use withCommand . For example: Specifying a startup command inside_block:startupCommand Executing a command Your test can execute a command inside a running container, similar to a docker exec call: Executing a command inside a running container inside_block:standaloneExec This can be useful for software that has a command line administration tool. You can also get the output (stdout/stderr) and exit code from the command - for example: Executing a command inside a running container and reading the result inside_block:execReadingStdout Environment variables To add environment variables to the container, use withEnv : Copy new GenericContainer (...) . withEnv ( "API_TOKEN" , "foo" ) + +### Files and volumes + +Path: `/sourcey/features/files.html` + +Files can be copied into the container before startup, or can be copied from the container after the container has started. + +Copying files Files can be copied into the container before startup, or can be copied from the container after the container has started. Note This is the recommended approach for portability cross-docker environments. Copying to a container before startup Copying files using MountableFile inside_block:copyToContainer Using Transferable , file content will be placed in the specified location. Copying files using Transferable inside_block:transferableFile Setting file mode is also possible. Copying files using Transferable with file mode inside_block:transferableWithFileMode Copying a file from a running container Copying files from a container inside_block:copyFileFromContainer + +### Waiting for containers to start or be ready + +Path: `/sourcey/features/startup-and-waits.html` + +Ordinarily Testcontainers will wait for up to 60 seconds for the container's first mapped network port to start listening. + +Wait strategies vs Startup strategies Wait strategy: is the container in a state that is useful for testing. This is generally approximated as 'can we talk to this container over the network'. However, there are quite a few variations and nuances. Startup strategy: did a container reach the desired running state. Almost always this just means 'wait until the container is running' - for a daemon process in a container this is the goal. Sometimes we need to wait until the container reaches a running state and then exits - this is the 'one shot startup' strategy, only used for cases where we need to run a one off command in a container but not a daemon. Wait Strategies Ordinarily Testcontainers will wait for up to 60 seconds for the container's first mapped network port to start listening. This simple measure provides a basic check whether a container is ready for use. Waiting for the first exposed port to start listening inside_block:waitForNetworkListening If the default 60s timeout is not sufficient, it can be altered with the withStartupTimeout() method. If waiting for a listening TCP port is not sufficient to establish whether the container is ready, you can use the waitingFor() method with other [ WaitStrategy ]( http://static.javadoc.io/org.testcontainers/testcontainers/{{ latest_version }}/org/testcontainers/containers/wait/strategy/WaitStrategy.html) implementations as shown below. HTTP Wait strategy examples You can choose to wait for an HTTP(S) endpoint to return a particular status code. Waiting for 200 OK inside_block:waitForSimpleHttp Variations on the HTTP wait strategy are supported, including: Waiting for multiple possible status codes inside_block:waitForHttpWithMultipleStatusCodes Waiting for a status code that matches a predicate Waiting for a status code that matches a predicate inside_block:waitForHttpWithStatusCodePredicate Using TLS inside_block:waitForHttpWithTls Healthcheck Wait strategy examples If the used image supports Docker's Healthcheck feature, you can directly leverage the healthy state of the container as your wait condition: inside_block:healthcheckWait Log output Wait Strategy In some situations a container's log output is a simple way to determine if it is ready or not. For example, we can wait for a `Ready' message in the container's logs as follows: inside_block:logMessageWait Other Wait Strategies For further options, check out the [ Wait ]( http://static.javadoc.io/org.testcontainers/testcontainers/{{ latest_version }}/org/testcontainers/containers/wait/strategy/Wait.html) convenience class, or the various subclasses of [ WaitStrategy ]( http://static.javadoc.io/org.testcontainers/testcontainers/{{ latest_version }}/org/testcontainers/containers/wait/strategy/WaitStrategy.html). If none of these options meet your requirements, you can create your own subclass of [ AbstractWaitStrategy ]( http://static.javadoc.io/org.testcontainers/testcontainers/{{ latest_version }}/org/testcontainers/containers/wait/strategy/AbstractWaitStrategy.html) with an appropriate wait mechanism in waitUntilReady() . The GenericContainer.waitingFor() method accepts any valid [ WaitStrategy ]( http://static.javadoc.io/org.testcontainers/testcontainers/{{ latest_version }}/org/testcontainers/containers/wait/strategy/WaitStrategy.html). Startup check Strategies Ordinarily Testcontainers will check that the container has reached the running state and has not exited. In order to do that inspect is executed against the container and state parameter is extracted. All logic is implemented in [ StartupCheckStrategy ]( http://static.javadoc.io/org.testcontainers/testcontainers/{{ latest_version }}/org/testcontainers/containers/startupcheck/StartupCheckStrategy.html) child classes. Running startup strategy example This is the strategy used by default. Testcontainers just checks if container is running. Implemented in [ IsRunningStartupCheckStrategy ]( http://static.javadoc.io/org.testcontainers/testcontainers/{{ latest_version }}/org/testcontainers/containers/startupcheck/IsRunningStartupCheckStrategy.html) class. One shot startup strategy example This strategy is intended for use with containers that only run briefly and exit of their own accord. As such, success is deemed to be when the container has stopped with exit code 0. Using one shot startup strategy inside_block:withOneShotStrategy Indefinite one shot startup strategy example Variant of one shot strategy that does not impose a timeout. Intended for situation such as when a long running task forms part of container startup. It has to be assumed that the container will stop of its own accord, either with a success or failure exit code. Using indefinite one shot startup strategy inside_block:withIndefiniteOneShotStrategy Minimum duration startup strategy example Checks that the container is running and has been running for a defined minimum period of time. Using minimum duration strategy inside_block:withMinimumDurationStrategy Other startup strategies If none of these options meet your requirements, you can create your own subclass of [ StartupCheckStrategy ]( http://static.javadoc.io/org.testcontainers/testcontainers/{{ latest_version }}/org/testcontainers/containers /startupcheck/StartupCheckStrategy.html) with an appropriate startup check mechanism in waitUntilStartupSuccessful() . Or you can leave it as is and just implement the checkStartupState(DockerClient dockerClient, String containerId) if you still want to check state periodically. Depending on another container Sometimes, a container relies on another container to be ready before it should start itself. An example of this might be a database that needs to be started before your application container can link to it. You can tell a container that it depends on another container by using the dependsOn method: Depending on another container inside_block:dependsOn + +### Accessing container logs + +Path: `/sourcey/features/container-logs.html` + +It is possible to capture container output using: + +It is possible to capture container output using: the getLogs() method, which simply returns a String snapshot of a container's entire log output the followOutput() method. This method accepts a Consumer and (optionally) a varargs list stating which of STDOUT, STDERR, or both, should be followed. If not specified, both will be followed. At present, container output will always begin from the time of container creation. Reading all logs (from startup time to present) getLogs() is the simplest mechanism for accessing container logs, and can be used as follows: Accessing all output (stdout and stderr) inside_block:docsGetAllLogs Accessing just stdout inside_block:docsGetStdOut Accessing just stderr inside_block:docsGetStdErr Streaming logs Testcontainers includes some out-of-the-box Consumer implementations that can be used with the streaming followOutput() model; examples follow. Streaming container output to an SLF4J logger Given an existing SLF4J logger instance named LOGGER: Copy Slf4jLogConsumer logConsumer = new Slf4jLogConsumer (LOGGER); container . followOutput (logConsumer); By default both standard out and standard error will both be emitted at INFO level. Standard error may be emitted at ERROR level, if desired: Copy Slf4jLogConsumer logConsumer = new Slf4jLogConsumer (LOGGER). withSeparateOutputStreams (); The Mapped Diagnostic Context (MDC) for emitted messages may be configured using the withMdc(...) option: Copy Slf4jLogConsumer logConsumer = new Slf4jLogConsumer (LOGGER). withMdc ( "key" , "value" ); or using an existing map of key-value pairs: Copy Slf4jLogConsumer logConsumer = new Slf4jLogConsumer (LOGGER). withMdc (map); Capturing container output as a String To stream logs live or customize the decoding, ToStringConsumer may be used: Copy ToStringConsumer toStringConsumer = new ToStringConsumer (); container . followOutput (toStringConsumer, OutputType . STDOUT ); String utf8String = toStringConsumer . toUtf8String (); // Or if the container output is not UTF-8 String otherString = toStringConsumer . toString ( CharSet . forName ( "ISO-8859-1" )); Waiting for container output to contain expected content WaitingConsumer will block until a frame of container output (usually a line) matches a provided predicate. A timeout may be specified, as shown in this example. Copy WaitingConsumer consumer = new WaitingConsumer (); container . followOutput (consumer, STDOUT); consumer . waitUntil (frame -> frame . getUtf8String (). contains ( "STARTED" ), 30 , TimeUnit . SECONDS ); Additionally, as the Java 8 Consumer functional interface is used, Consumers may be composed together. This is useful, for example, to capture all the container output but only when a matching string has been found. e.g.: Copy WaitingConsumer waitingConsumer = new WaitingConsumer (); ToStringConsumer toStringConsumer = new ToStringConsumer (); Consumer & lt;OutputFrame & gt; composedConsumer = toStringConsumer . andThen (waitingConsumer); container . followOutput (composedConsumer); waitingConsumer . waitUntil (frame -> frame . getUtf8String (). contains ( "STARTED" ), 30 , TimeUnit . SECONDS ); String utf8String = toStringConsumer . toUtf8String (); + +### Creating images on-the-fly + +Path: `/sourcey/features/creating-images.html` + +In situations where there is no pre-existing Docker image, Testcontainers can create a new temporary image on-the-fly from a Dockerfile. For example, when the component under test is the Docker image itself, or when an existing base image needs to be customized for specific test(s). + +Overview In situations where there is no pre-existing Docker image, Testcontainers can create a new temporary image on-the-fly from a Dockerfile. For example, when the component under test is the Docker image itself, or when an existing base image needs to be customized for specific test(s). Simply pass a configured instance of ImageFromDockerfile as a constructor parameter to GenericContainer . Testcontainers will docker build a temporary container image, and will use it when creating the container. Dockerfile from String, file or classpath resource ImageFromDockerfile accepts arbitrary files, strings or classpath resources to be used as files in the build context. At least one of these needs to be a Dockerfile . Copy GenericContainer container = new GenericContainer ( new ImageFromDockerfile () . withFileFromString ( "folder/someFile.txt" , "hello" ) . withFileFromClasspath ( "test.txt" , "mappable-resource/test-resource.txt" ) . withFileFromClasspath ( "Dockerfile" , "mappable-dockerfile/Dockerfile" )) The following methods may be used to provide the Dockerfile and any other required build context files: withFileFromString(buildContextPath, content) withFileFromClasspath(buildContextPath, classpathPath) withFileFromPath(buildContextPath, filesystemPath) withFileFromFile(buildContextPath, filesystemFile) Info In older versions of Testcontainers (before 1.3.0) it was necessary to explicitly declare each file that needed to be present in the Docker build context. This can be replaced with the following syntax: Passing an entire directory of files to the Dockerfile build context inside_block:docsShowRecursiveFileInclusion Where RESOURCE_PATH is the path to a directory containing a Dockerfile and any files that it needs to refer to. Doing this is equivalent to docker build RESOURCE_PATH on the command line. To mimic docker build . , RESOURCE_PATH would simply be set to . as well. Dockerfile DSL If a static Dockerfile is not sufficient (e.g. your test needs to cover many variations that are best generated programmatically), there is a DSL available to allow Dockerfiles to be defined in code. e.g.: Copy new GenericContainer ( new ImageFromDockerfile () . withDockerfileFromBuilder (builder -> builder . from ( "alpine:3.17" ) . run ( "apk add --update nginx" ) . cmd ( "nginx" , "-g" , "daemon off;" ) . build ())) . withExposedPorts ( 80 ); See ParameterizedDockerfileContainerTest for a very basic example of using this in conjunction with JUnit parameterized testing. Automatic deletion Temporary container images will be automatically removed when the test JVM shuts down. If this is not desired and the image should be retained between tests, pass a stable image name and false flag to the ImageFromDockerfile constructor. Retaining the image between tests will use Docker's image cache to accelerate subsequent test runs. By default the no-args constructor will use an image name of the form testcontainers/ + random string: public ImageFromDockerfile() public ImageFromDockerfile(String dockerImageName) public ImageFromDockerfile(String dockerImageName, boolean deleteOnExit) Alternative Dockerfiles Normally Docker will automatically build an image from any /Dockerfile that it finds in the root of the build context. To override this behaviour, use .withDockerfilePath("./Name-Of-Other-Dockerfile") . Build Args Build Args may be used to allow lightweight parameterization. To specify build args, use .withBuildArg("varname", "value") or provide a Map of args using .withBuildArgs(map) . + +### Custom configuration + +Path: `/sourcey/features/configuration.html` + +You can override some default properties if your environment requires that. + +You can override some default properties if your environment requires that. Configuration locations The configuration will be loaded from multiple locations. Properties are considered in the following order: Environment variables .testcontainers.properties in user's home folder. Example locations: Linux: /home/myuser/.testcontainers.properties Windows: C:/Users/myuser/.testcontainers.properties macOS: /Users/myuser/.testcontainers.properties testcontainers.properties on the classpath. Note that when using environment variables, configuration property names should be set in upper case with underscore separators, preceded by TESTCONTAINERS_ - e.g. checks.disable becomes TESTCONTAINERS_CHECKS_DISABLE . The classpath testcontainers.properties file may exist within the local codebase (e.g. within the src/test/resources directory) or within library dependencies that you may have. Any such configuration files will have their contents merged. If any keys conflict, the value will be taken on the basis of the first value found in: 'local' classpath (i.e. where the URL of the file on the classpath begins with file: ), then other classpath locations (i.e. JAR files) - considered in alphabetical order of path to provide deterministic ordering. Disabling the startup checks checks.disable = [true|false] Before running any containers Testcontainers will perform a set of startup checks to ensure that your environment is configured correctly. Usually they look like this: Copy ℹ︎ Checking the system... ✔ Docker version should be at least 1.6.0 ✔ File should be mountable ✔ A port exposed by a docker container should be accessible It takes a couple of seconds, but if you want to speed up your tests, you can disable the checks once you have everything configured. Add checks.disable=true to your $HOME/.testcontainers.properties to completely disable them. Customizing images Note This approach is discouraged and deprecated, but is documented for completeness. Overriding individual image names via configuration may be removed in 2021. See Image Name Substitution for other strategies for substituting image names to pull from other registries. Testcontainers uses public Docker images to perform different actions like startup checks, VNC recording and others. Some companies disallow the usage of Docker Hub, but you can override *.image properties with your own images from your private registry to workaround that. ryuk.container.image = testcontainers/ryuk:0.3.3 Performs fail-safe cleanup of containers, and always required (unless Ryuk is disabled ) tinyimage.container.image = alpine:3.17 Used to check whether images can be pulled at startup, and always required (unless startup checks are disabled ) sshd.container.image = testcontainers/sshd:1.4.0 Required if exposing host ports to containers vncrecorder.container.image = testcontainers/vnc-recorder:1.3.0 Used by VNC recorder in Testcontainers' Selenium integration socat.container.image = alpine/socat compose.container.image = docker/compose:1.8.0 Required if using Docker Compose kafka.container.image = confluentinc/cp-kafka Used by KafkaContainer localstack.container.image = localstack/localstack Used by LocalStack pulsar.container.image = apachepulsar/pulsar:2.2.0 Used by Apache Pulsar Customizing Ryuk resource reaper ryuk.container.image = testcontainers/ryuk:0.3.3 The resource reaper is responsible for container removal and automatic cleanup of dead containers at JVM shutdown ryuk.container.privileged = true In some environments ryuk must be started in privileged mode to work properly (--privileged flag) Disabling Ryuk Ryuk must be started as a privileged container. If your environment already implements automatic cleanup of containers after the execution, but does not allow starting privileged containers, you can turn off the Ryuk container by setting TESTCONTAINERS_RYUK_DISABLED environment variable to true . !!!tip Note that Testcontainers will continue doing the cleanup at JVM's shutdown, unless you kill -9 your JVM process. Customizing image pull behaviour pull.timeout = 120 By default Testcontainers will timeout if pull takes more than this duration (in seconds) pull.pause.timeout = 30 By default Testcontainers will abort the pull of an image if the pull appears stalled (no data transferred) for longer than this duration (in seconds). Customizing client ping behaviour client.ping.timeout = 10 Specifies for how long Testcontainers will try to connect to the Docker client to obtain valid info about the client before giving up and trying next strategy, if applicable (in seconds). Customizing Docker host detection Testcontainers will attempt to detect the Docker environment and configure everything to work automatically. However, sometimes customization is required. Testcontainers will respect the following environment variables : DOCKER_HOST = unix:///var/run/docker.sock See Docker environment variables TESTCONTAINERS_DOCKER_SOCKET_OVERRIDE Path to Docker's socket. Used by Ryuk, Docker Compose, and a few other containers that need to perform Docker actions. Example: /var/run/docker-alt.sock TESTCONTAINERS_HOST_OVERRIDE Docker's host on which ports are exposed. Example: docker.svc.local For advanced users, the Docker host connection can be configured via configuration in ~/.testcontainers.properties . Note that these settings require use of the EnvironmentAndSystemPropertyClientProviderStrategy . The example below illustrates usage: Copy docker.client.strategy=org.testcontainers.dockerclient.EnvironmentAndSystemPropertyClientProviderStrategy docker.host=tcp\://my.docker.host\:1234 # Equivalent to the DOCKER_HOST environment variable. Colons should be escaped. docker.tls.verify=1 # Equivalent to the DOCKER_TLS_VERIFY environment variable docker.cert.path=/some/path # Equivalent to the DOCKER_CERT_PATH environment variable In addition, you can deactivate this behaviour by specifying: Copy dockerconfig.source=autoIgnoringUserProperties # 'auto' by default + +### Image name substitution + +Path: `/sourcey/features/image-name-substitution.html` + +Testcontainers supports automatic substitution of Docker image names. + +Testcontainers supports automatic substitution of Docker image names. This allows replacement of an image name specified in test code with an alternative name - for example, to replace the name of a Docker Hub image dependency with an alternative hosted on a private image registry. This is advisable to avoid Docker Hub rate limiting , and some companies will prefer this for policy reasons. This page describes four approaches for image name substitution: Manual substitution - not relying upon an automated approach Using an Image Name Substitutor: Developing a custom function for transforming image names on the fly Overriding image names individually in configuration It is assumed that you have already set up a private registry hosting all the Docker images your build requires . Manual substitution Consider this if: You use only a few images and updating code is not a chore All developers and CI machines in your organisation have access to a common registry server You also use one of the automated mechanisms to substitute the images that Testcontainers itself requires This approach simply entails modifying test code manually, e.g. changing: For example, you may have a test that uses the mysql container image from Docker Hub: Direct Docker Hub image name inside_block:directDockerHubReference to: Private registry image name inside_block:hardcodedMirror Automatically modifying Docker Hub image names Testcontainers can be configured to modify Docker Hub image names on the fly to apply a prefix string. Consider this if: Developers and CI machines need to use different image names. For example, developers are able to pull images from Docker Hub, but CI machines need to pull from a private registry Your private registry has copies of images from Docker Hub where the names are predictable, and just adding a prefix is enough. For example, registry.mycompany.com/mirror/mysql:8.0.36 can be derived from the original Docker Hub image name ( mysql:8.0.36 ) with a consistent prefix string: registry.mycompany.com/mirror/ In this case, image name references in code are unchanged . i.e. you would leave as-is: Unchanged direct Docker Hub image name inside_block:directDockerHubReference You can then configure Testcontainers to apply the prefix registry.mycompany.com/mirror/ to every image that it tries to pull from Docker Hub. This can be done in one of two ways: Setting environment variables TESTCONTAINERS_HUB_IMAGE_NAME_PREFIX=registry.mycompany.com/mirror/ Via config file, setting hub.image.name.prefix in either: the ~/.testcontainers.properties file in your user home directory, or a file named testcontainers.properties on the classpath Testcontainers will automatically apply the prefix to every image that it pulls from Docker Hub - please verify that all the required images exist in your registry. Testcontainers will not apply the prefix to: non-Hub image names (e.g. where another registry is set) Docker Hub image names where the hub registry is explicitly part of the name (i.e. anything with a docker.io or registry.hub.docker.com host part) Developing a custom function for transforming image names on the fly Consider this if: You have complex rules about which private registry images should be used as substitutes, e.g.: non-deterministic mapping of names meaning that a name prefix cannot be used rules depending upon developer identity or location or you wish to add audit logging of images used in the build or you wish to prevent accidental usage of images that are not on an approved list In this case, image name references in code are unchanged . i.e. you would leave as-is: Unchanged direct Docker Hub image name inside_block:directDockerHubReference You can implement a custom image name substitutor by: subclassing org.testcontainers.utility.ImageNameSubstitutor configuring Testcontainers to use your custom implementation The following is an example image substitutor implementation: Example Image Substitutor block:ExampleImageNameSubstitutor Testcontainers can be configured to find it at runtime via configuration. To do this, create or modify a file on the classpath named testcontainers.properties . For example: src/test/resources/testcontainers.properties Copy image.substitutor=com.mycompany.testcontainers.ExampleImageNameSubstitutor Note that it is also possible to provide this same configuration property: in a testcontainers.properties file at the root of a library JAR file (useful if you wish to distribute a drop-in image substitutor JAR within an organization) in a properties file in the user's home directory ( ~/.testcontainers.properties ; note the leading . ) or as an environment variable (e.g. TESTCONTAINERS_IMAGE_SUBSTITUTOR=com.mycompany.testcontainers.ExampleImageNameSubstitutor ). Please see the documentation on configuration mechanisms for more information. Also, you can use the ServiceLoader mechanism to provide the fully qualified class name of the ImageNameSubstitutor implementation: src/test/resources/META-INF/services/org.testcontainers.utility.ImageNameSubstitutor Copy com.mycompany.testcontainers.ExampleImageNameSubstitutor Overriding image names individually in configuration Note This approach is discouraged and deprecated, but is documented for completeness. Please consider one of the other approaches outlined in this page instead. Overriding individual image names via configuration may be removed in the future. Consider this if: You have many references to image names in code and changing them is impractical, and None of the other options are practical for you In this case, image name references in code are left unchanged . i.e. you would leave as-is: Unchanged direct Docker Hub image name inside_block:directDockerHubReference You can force Testcontainers to substitute in a different image using a configuration file , which allows some (but not all) container names to be substituted. + +### Advanced options + +Path: `/sourcey/features/advanced-options.html` + +To add a custom label to the container, use `withLabel`: + +Container labels To add a custom label to the container, use withLabel : Adding a single label inside_block:single_label Additionally, multiple labels may be applied together from a map: Adding multiple labels inside_block:multiple_labels Image Pull Policy By default, the container image is retrieved from the local Docker images cache. This works well when running against a specific version, but for images with a static tag (i.e. 'latest') this may lead to a newer version not being pulled. It is possible to specify an Image Pull Policy to determine at runtime whether an image should be pulled or not: Setting image pull policy inside_block:built_in_image_pull_policy ... or providing a function: Custom image pull policy inside_block:custom_image_pull_policy You can also configure Testcontainers to use your custom implementation by using pull.policy src/test/resources/testcontainers.properties Copy pull.policy=com.mycompany.testcontainers.ExampleImagePullPolicy You can also use the provided implementation to always pull images src/test/resources/testcontainers.properties Copy pull.policy=org.testcontainers.images.AlwaysPullPolicy Please see the documentation on configuration mechanisms for more information. Customizing the container Using docker-java It is possible to use the docker-java API directly to customize containers before creation. This is useful if there is a need to use advanced Docker features that are not exposed by the Testcontainers API. Any customizations you make using withCreateContainerCmdModifier will be applied on top of the container definition that Testcontainers creates, but before it is created. For example, this can be used to change the container hostname: Using modifier to change hostname inside_block:hostname ... or modify container memory (see this if it does not appear to work): Using modifier to change memory limits inside_block:memory Note It is recommended to use this sparingly, and follow changes to the docker-java API if you choose to use this. It is typically quite stable, though. For what is possible, consult the docker-java CreateContainerCmd source code . Using CreateContainerCmdModifier Testcontainers provides a CreateContainerCmdModifier to customize docker-java CreateContainerCmd via Service Provider Interface (SPI) mechanism. CreateContainerCmd example implementation The previous implementation should be registered in META-INF/services/org.testcontainers.core.CreateContainerCmdModifier file. Warning CreateContainerCmdModifier implementation will apply to all containers created by Testcontainers. Parallel Container Startup Usually, containers are started sequentially when more than one container is used. Using Startables.deepStart(container1, container2, ...).join() will start all containers in parallel. This can be advantageous to reduce the impact of the container startup overhead. + +### Reusable Containers (Experimental) + +Path: `/sourcey/features/reuse.html` + +The *Reusable* feature keeps the containers running and next executions with the same container configuration will reuse it. To use it, start the container manually by calling `start()` method, do not call `stop()` method directly or indirectly via `try-with-resources` or `JUnit integration`, and enable it manually through an opt-in mechanism per environment. To reuse a container, the container configuration **must be the same**. + +Warning Reusable Containers is still an experimental feature and the behavior can change. Those containers won't stop after all tests are finished. The Reusable feature keeps the containers running and next executions with the same container configuration will reuse it. To use it, start the container manually by calling start() method, do not call stop() method directly or indirectly via try-with-resources or JUnit integration , and enable it manually through an opt-in mechanism per environment. To reuse a container, the container configuration must be the same . Note Reusable containers are not suited for CI usage and as an experimental feature not all Testcontainers features are fully working (e.g., resource cleanup or networking). How to use it Enable Reusable Containers through environment variable TESTCONTAINERS_REUSE_ENABLE=true through user property file ~/.testcontainers.properties , by adding testcontainers.reuse.enable=true not through classpath properties file see this comment Define a container and subscribe to reuse the container using withReuse(true) Copy GenericContainer container = new GenericContainer ( "redis:6-alpine" ) . withExposedPorts ( 6379 ) . withReuse ( true ) Start the container manually by using container.start() Reusable Container with Testcontainers JDBC URL If using the Testcontainers JDBC URL support the URL must follow the pattern of jdbc:tc:mysql:8.0.36:///databasename?TC_REUSABLE=true . TC_REUSABLE=true is set as a parameter of the JDBC URL. + +### Database containers + +Path: `/sourcey/modules/databases/` + +You might want to use Testcontainers' database support: + +Overview You might want to use Testcontainers' database support: Instead of H2 database for DAO unit tests that depend on database features that H2 doesn't emulate. Testcontainers is not as performant as H2, but does give you the benefit of 100% database compatibility (since it runs a real DB inside of a container). Instead of a database running on the local machine or in a VM for DAO unit tests or end-to-end integration tests that need a database to be present. In this context, the benefit of Testcontainers is that the database always starts in a known state, without any contamination between test runs or on developers' local machines. Note Of course, it's still important to have as few tests that hit the database as possible, and make good use of mocks for components higher up the stack. See JDBC and R2DBC for information on how to use Testcontainers with SQL-like databases. + +### JDBC support + +Path: `/sourcey/modules/databases/jdbc.html` + +You can obtain a temporary database in one of two ways: + +You can obtain a temporary database in one of two ways: Using a specially modified JDBC URL : after making a very simple modification to your system's JDBC URL string, Testcontainers will provide a disposable stand-in database that can be used without requiring modification to your application code. JUnit @Rule/@ClassRule : this mode starts a database inside a container before your tests and tears it down afterwards. Database containers launched via JDBC URL scheme As long as you have Testcontainers and the appropriate JDBC driver on your classpath, you can simply modify regular JDBC connection URLs to get a fresh containerized instance of the database each time your application starts up. N.B: TC needs to be on your application's classpath at runtime for this to work For Spring Boot (Before version 2.3.0 ) you need to specify the driver manually spring.datasource.driver-class-name=org.testcontainers.jdbc.ContainerDatabaseDriver Original URL : jdbc:mysql://localhost:3306/databasename Insert tc: after jdbc: as follows. Note that the hostname, port and database name will be ignored; you can leave these as-is or set them to any value. Note We will use /// (host-less URIs) from now on to emphasis the unimportance of the host:port pair. From Testcontainers' perspective, jdbc:mysql:8.0.36://localhost:3306/databasename and jdbc:mysql:8.0.36:///databasename is the same URI. Warning If you're using the JDBC URL support, there is no need to instantiate an instance of the container - Testcontainers will do it automagically. JDBC URL examples Using ClickHouse jdbc:tc:clickhouse:18.10.3:///databasename Using CockroachDB jdbc:tc:cockroach:v21.2.3:///databasename Using CrateDB jdbc:tc:cratedb:5.2.3:///databasename Using DB2 jdbc:tc:db2:11.5.0.0a:///databasename Using MariaDB jdbc:tc:mariadb:10.3.39:///databasename Using MySQL jdbc:tc:mysql:8.0.36:///databasename Using MSSQL Server jdbc:tc:sqlserver:2017-CU12:///databasename Using OceanBase jdbc:tc:oceanbasece:4.2.1-lts:///databasename Using Oracle jdbc:tc:oracle:21-slim-faststart:///databasename Using PostGIS jdbc:tc:postgis:9.6-2.5:///databasename Using PostgreSQL jdbc:tc:postgresql:9.6.8:///databasename Using QuestDB jdbc:tc:questdb:6.5.3:///databasename Using TimescaleDB jdbc:tc:timescaledb:2.1.0-pg13:///databasename Using PGVector jdbc:tc:pgvector:pg16:///databasename Using TiDB jdbc:tc:tidb:v6.1.0:///databasename Using Timeplus jdbc:tc:timeplus:2.3.21:///databasename Using Trino jdbc:tc:trino:352://localhost/memory/default Using YugabyteDB jdbc:tc:yugabyte:2.14.4.0-b26:///databasename Using a classpath init script Testcontainers can run an init script after the database container is started, but before your code is given a connection to it. The script must be on the classpath, and is referenced as follows: jdbc:tc:mysql:8.0.36:///databasename?TC_INITSCRIPT=somepath/init_mysql.sql This is useful if you have a fixed script for setting up database schema, etc. Using an init script from a file If the init script path is prefixed file: , it will be loaded from a file (relative to the working directory, which will usually be the project root). jdbc:tc:mysql:8.0.36:///databasename?TC_INITSCRIPT=file:src/main/resources/init_mysql.sql Using an init function Instead of running a fixed script for DB setup, it may be useful to call a Java function that you define. This is intended to allow you to trigger database schema migration tools. To do this, add TC_INITFUNCTION to the URL as follows, passing a full path to the class name and method: jdbc:tc:mysql:8.0.36:///databasename?TC_INITFUNCTION=org.testcontainers.jdbc.JDBCDriverTest::sampleInitFunction The init function must be a public static method which takes a java.sql.Connection as its only parameter, e.g. Copy public class JDBCDriverTest { public static void sampleInitFunction ( Connection connection ) throws SQLException { // e.g. run schema setup or Flyway/liquibase/etc DB migrations here... } ... Running container in daemon mode By default database container is being stopped as soon as last connection is closed. There are cases when you might need to start container and keep it running till you stop it explicitly or JVM is shutdown. To do this, add TC_DAEMON parameter to the URL as follows: jdbc:tc:mysql:8.0.36:///databasename?TC_DAEMON=true With this parameter database container will keep running even when there's no open connections. Running container with tmpfs options Container can have tmpfs mounts for storing data in host memory. This is useful if you want to speed up your database tests. Be aware that the data will be lost when the container stops. To pass this option to the container, add TC_TMPFS parameter to the URL as follows: jdbc:tc:postgresql:9.6.8:///databasename?TC_TMPFS=/testtmpfs:rw If you need more than one option, separate them by comma (e.g. TC_TMPFS=key:value,key1:value1&other_parameters=foo ). For more information about tmpfs mount, see the official Docker documentation . Database container objects In case you can't use the URL support, or need to fine-tune the container, you can instantiate it yourself. Add a @Rule or @ClassRule to your test class, e.g.: Copy public class SimpleMySQLTest { @ Rule public MySQLContainer mysql = new MySQLContainer (); Now, in your test code (or a suitable setup method), you can obtain details necessary to connect to this database: mysql.getJdbcUrl() provides a JDBC URL your code can connect to mysql.getUsername() provides the username your code should pass to the driver mysql.getPassword() provides the password your code should pass to the driver Note that if you use @Rule , you will be given an isolated container for each test method. If you use @ClassRule , you will get on isolated container for all the methods in the test class. Examples/Tests: MySQL PostgreSQL + +### Postgres Module + +Path: `/sourcey/modules/databases/postgres.html` + +Testcontainers module for PostgresSQL + +Testcontainers module for PostgresSQL Usage example You can start a PostgreSQL container instance from any Java application by using: Container creation inside_block:container See Database containers for documentation and usage that is common to all relational database container types. Testcontainers JDBC URL PostgreSQL: jdbc:tc:postgresql:9.6.8:///databasename PostGIS: jdbc:tc:postgis:9.6-2.5:///databasename TimescaleDB: jdbc:tc:timescaledb:2.1.0-pg13:///databasename PGvector: jdbc:tc:pgvector:pg16:///databasename See JDBC for documentation. Compatible images PostgreSQLContainer can also be used with the following images: pgvector/pgvector Using pgvector inside_block:pgvectorContainer postgis/postgis Using PostGIS inside_block:postgisContainer timescale/timescaledb Using TimescaleDB inside_block:timescaledbContainer Adding this module to your project dependencies Add the following dependency to your pom.xml / build.gradle file: Gradle Copy testImplementation "org.testcontainers:testcontainers-postgresql:{{latest_version}}" Maven Copy dependency > groupId > org.testcontainers groupId > artifactId > testcontainers-postgresql artifactId > version > {{latest_version}} version > scope > test scope > dependency > Hint Adding this Testcontainers library JAR will not automatically add a database driver JAR to your project. You should ensure that your project also has a suitable database driver as a dependency. + +### MySQL Module + +Path: `/sourcey/modules/databases/mysql.html` + +Testcontainers module for MySQL + +Testcontainers module for MySQL Usage example You can start a MySQL container instance from any Java application by using: Container definition inside_block:container See Database containers for documentation and usage that is common to all relational database container types. Testcontainers JDBC URL jdbc:tc:mysql:8.0.36:///databasename See JDBC for documentation. Overriding MySQL my.cnf settings For MySQL databases, it is possible to override configuration settings using resources on the classpath. Assuming somepath/mysql_conf_override is a directory on the classpath containing .cnf files, the following URL can be used: jdbc:tc:mysql:8.0.36://hostname/databasename?TC_MY_CNF=somepath/mysql_conf_override Any .cnf files in this classpath directory will be mapped into the database container's /etc/mysql/conf.d directory, and will be able to override server settings when the container starts. MySQL root user password If no custom password is specified, the container will use the default user password test for the root user as well. When you specify a custom password for the database user, this will also act as the password of the MySQL root user automatically. Adding this module to your project dependencies Add the following dependency to your pom.xml / build.gradle file: Gradle Copy testImplementation "org.testcontainers:testcontainers-mysql:{{latest_version}}" Maven Copy dependency > groupId > org.testcontainers groupId > artifactId > testcontainers-mysql artifactId > version > {{latest_version}} version > scope > test scope > dependency > Hint Adding this Testcontainers library JAR will not automatically add a database driver JAR to your project. You should ensure that your project also has a suitable database driver as a dependency. + +### MongoDB Module + +Path: `/sourcey/modules/databases/mongodb.html` + +The MongoDB module provides two Testcontainers for MongoDB unit testing: + +The MongoDB module provides two Testcontainers for MongoDB unit testing: MongoDBContainer - the core MongoDB database MongoDBAtlasLocalContainer - the core MongoDB database combined with MongoDB Atlas Search + Atlas Vector Search MongoDBContainer Usage example The following example shows how to create a MongoDBContainer: Creating a MongoDB container inside_block:creatingMongoDBContainer And how to start it: Starting a MongoDB container inside_block:startingMongoDBContainer Note To construct a multi-node MongoDB cluster, consider the mongodb-replica-set project Motivation Implement a reusable, cross-platform, simple to install solution that doesn't depend on fixed ports to test MongoDB transactions. General info MongoDB starting from version 4 supports multi-document transactions only for a replica set. For instance, to initialize a single node replica set on fixed ports via Docker, one has to do the following: Run a MongoDB container of version 4 and up specifying --replSet command Initialize a single replica set via executing a proper command Wait for the initialization to complete Provide a special url for a user to employ with a MongoDB driver without specifying replicaSet As we can see, there is a lot of operations to execute and we even haven't touched a non-fixed port approach. That's where the MongoDBContainer might come in handy. MongoDBAtlasLocalContainer Usage example The following example shows how to create a MongoDBAtlasLocalContainer: Creating a MongoDB Atlas Local Container inside_block:creatingAtlasLocalContainer And how to start it: Start the Container inside_block:startingAtlasLocalContainer The connection string provided by the MongoDBAtlasLocalContainer's getConnectionString() method includes the dynamically allocated port: Get the Connection String inside_block:getConnectionStringAtlasLocalContainer e.g. mongodb://localhost:12345/?directConnection=true References MongoDB Atlas Local combines the MongoDB database engine with MongoT, a sidecar process for advanced searching capabilities built by MongoDB and powered by Apache Lucene . The container (mongodb/mongodb-atlas-local) documentation can be found here . General information about Atlas Search can be found here . Adding this module to your project dependencies Add the following dependency to your pom.xml / build.gradle file: Gradle Copy testImplementation "org.testcontainers:testcontainers-mongodb:{{latest_version}}" Maven Copy dependency > groupId > org.testcontainers groupId > artifactId > testcontainers-mongodb artifactId > version > {{latest_version}} version > scope > test scope > dependency > Hint Adding this Testcontainers library JAR will not automatically add a database driver JAR to your project. You should ensure that your project also has a suitable database driver as a dependency Copyright Copyright (c) 2019 Konstantin Silaev silaev256@gmail.com + +### Kafka Module + +Path: `/sourcey/modules/kafka.html` + +Testcontainers can be used to automatically instantiate and manage Apache Kafka containers. + +Testcontainers can be used to automatically instantiate and manage Apache Kafka containers. Currently, two different Kafka images are supported: org.testcontainers.kafka.ConfluentKafkaContainer supports confluentinc/cp-kafka org.testcontainers.kafka.KafkaContainer supports apache/kafka and apache/kafka-native Note org.testcontainers.containers.KafkaContainer is deprecated. Please use org.testcontainers.kafka.ConfluentKafkaContainer or org.testcontainers.kafka.KafkaContainer instead, depending on the used image. Benefits Running a single node Kafka installation with just one line of code No need to manage external Zookeeper installation, required by Kafka. Example Using org.testcontainers.kafka.KafkaContainer Create a KafkaContainer to use it in your tests: Creating a KafkaContainer inside_block:constructorWithVersion Now your tests or any other process running on your machine can get access to running Kafka broker by using the following bootstrap server location: Bootstrap Servers inside_block:getBootstrapServers Using org.testcontainers.kafka.ConfluentKafkaContainer Note Compatible with confluentinc/cp-kafka images version 7.4.0 and later. Create a ConfluentKafkaContainer to use it in your tests: Creating a ConfluentKafkaContainer inside_block:constructorWithVersion Options Using Kraft mode Note Only available for org.testcontainers.containers.KafkaContainer KRaft mode was declared production ready in 3.3.1 (confluentinc/cp-kafka:7.3.x) Kraft mode inside_block:withKraftMode See the versions interoperability matrix for more details. Register listeners There are scenarios where additional listeners are needed because the consumer/producer can be in another container in the same network or a different process where the port to connect differs from the default exposed port. E.g Toxiproxy . Register additional listener inside_block:registerListener Container defined in the same network: Create kcat container inside_block:createKCatContainer Client using the new registered listener: Produce/Consume via new listener inside_block:produceConsumeMessage Adding this module to your project dependencies Add the following dependency to your pom.xml / build.gradle file: Gradle Copy testImplementation "org.testcontainers:testcontainers-kafka:{{latest_version}}" Maven Copy dependency > groupId > org.testcontainers groupId > artifactId > testcontainers-kafka artifactId > version > {{latest_version}} version > scope > test scope > dependency > + +### LocalStack Module + +Path: `/sourcey/modules/localstack.html` + +Testcontainers module for LocalStack, 'a fully functional local AWS cloud stack', to develop and test your cloud and serverless apps without actually using the cloud. + +Testcontainers module for LocalStack , 'a fully functional local AWS cloud stack', to develop and test your cloud and serverless apps without actually using the cloud. Usage example You can start a LocalStack container instance from any Java application by using: Container creation inside_block:container Environment variables listed in the LocalStack configuration documentation may be used to customize LocalStack's configuration. Use the .withEnv(key, value) method on LocalStackContainer to apply configuration settings. Note Starting March 23, 2026, localstack/localstack requires authentication via a LOCALSTACK_AUTH_TOKEN environment variable. Without it, the container will fail to start. Use .withEnv("LOCALSTACK_AUTH_TOKEN", System.getenv("LOCALSTACK_AUTH_TOKEN")) to pass the token. See the LocalStack blog post for more details. Creating a client using AWS SDK AWS SDK V2 inside_block:with_aws_sdk_v2 Adding this module to your project dependencies Add the following dependency to your pom.xml / build.gradle file: Gradle Copy testImplementation "org.testcontainers:testcontainers-localstack:{{latest_version}}" Maven Copy dependency > groupId > org.testcontainers groupId > artifactId > testcontainers-localstack artifactId > version > {{latest_version}} version > scope > test scope > dependency > + +### Toxiproxy Module + +Path: `/sourcey/modules/toxiproxy.html` + +Testcontainers module for Shopify's Toxiproxy. This TCP proxy can be used to simulate network failure conditions. + +Testcontainers module for Shopify's Toxiproxy . This TCP proxy can be used to simulate network failure conditions. You can simulate network failures: between Java code and containers, ideal for testing resilience features of client code between containers, for testing resilience and emergent behaviour of multi-container systems if desired, between Java code/containers and external resources (non-Dockerized!), for scenarios where not all dependencies can be/have been dockerized Testcontainers Toxiproxy support allows resilience features to be easily verified as part of isolated dev/CI testing. This allows earlier testing of resilience features, and broader sets of failure conditions to be covered. Usage example A Toxiproxy container can be placed in between test code and a container, or in between containers. In either scenario, it is necessary to create a ToxiproxyContainer instance on the same Docker network, as follows: Creating a Toxiproxy container inside_block:creatingProxy Next, it is necessary to instruct Toxiproxy to start proxying connections. Each ToxiproxyContainer can proxy to many target containers if necessary. We do this as follows: Starting proxying connections to a target container inside_block:obtainProxyObject To establish a connection from the test code (on the host machine) to the target container via Toxiproxy, we obtain Toxiproxy's proxy host IP and port: Obtaining proxied host and port inside_block:obtainProxiedHostAndPortForHostMachine Code under test should connect to this proxied host IP and port. Note Currently, ToxiProxyContainer will reserve 31 ports, starting at 8666. Other containers should connect to this proxied host and port. Having done this, it is possible to trigger failure conditions ('Toxics') through the proxy.toxics() object: bandwidth - Limit a connection to a maximum number of kilobytes per second. latency - Add a delay to all data going through the proxy. The delay is equal to latency +/- jitter . slicer - Slices TCP data up into small bits, optionally adding a delay between each sliced "packet". slowClose - Delay the TCP socket from closing until delay milliseconds has elapsed. timeout - Stops all data from getting through, and closes the connection after timeout . If timeout is 0 , the connection won't close, and data will be delayed until the toxic is removed. limitData - Closes connection when transmitted data exceeded limit. Please see the Toxiproxy documentation for full details on the available Toxics. As one example, we can introduce latency and random jitter to proxied connections as follows: Adding latency to a connection inside_block:addingLatency Additionally we can disable the proxy to simulate a complete interruption to the network connection: Cutting a connection inside_block:disableProxy Adding this module to your project dependencies Add the following dependency to your pom.xml / build.gradle file: Gradle Copy testImplementation "org.testcontainers:testcontainers-toxiproxy:{{latest_version}}" Maven Copy dependency > groupId > org.testcontainers groupId > artifactId > testcontainers-toxiproxy artifactId > version > {{latest_version}} version > scope > test scope > dependency > Acknowledgements This module was inspired by a hotels.com blog post . + +### Jupiter / JUnit 5 + +Path: `/sourcey/test-framework-integration/junit-5.html` + +This module provides an API that is based on the JUnit Jupiter extension model. + +This module provides an API that is based on the JUnit Jupiter extension model. The extension supports two modes: containers that are restarted for every test method containers that are shared between all methods of a test class Note that Jupiter/JUnit 5 integration is packaged as a separate library JAR; see below for details. Extension Jupiter integration is provided by means of the @Testcontainers annotation. The extension finds all fields that are annotated with @Container and calls their container lifecycle methods (methods on the Startable interface). Containers declared as static fields will be shared between test methods. They will be started only once before any test method is executed and stopped after the last test method has executed. Containers declared as instance fields will be started and stopped for every test method. Note: This extension has only been tested with sequential test execution. Using it with parallel test execution is unsupported and may have unintended side effects. Example: Mixed Lifecycle inside_block:testClass Examples To use the Testcontainers extension annotate your test class with @Testcontainers . Restarted containers To define a restarted container, define an instance field inside your test class and annotate it with the @Container annotation. Restarted Containers inside_block:testClass Shared containers Shared containers are defined as static fields in a top level test class and have to be annotated with @Container . Note that shared containers can't be declared inside nested test classes. This is because nested test classes have to be defined non-static and can't therefore have static fields. Shared Container lines:18-23,32-33,35-36 Singleton containers Note that the singleton container pattern is also an option when using JUnit 5. Limitations This extension has only been tested with sequential test execution. Using it with parallel test execution is unsupported and may have unintended side effects. Adding Testcontainers JUnit 5 support to your project dependencies Add the following dependency to your pom.xml / build.gradle file: Gradle Copy testImplementation "org.testcontainers:testcontainers-junit-jupiter:{{latest_version}}" Maven Copy dependency > groupId > org.testcontainers groupId > artifactId > testcontainers-junit-jupiter artifactId > version > {{latest_version}} version > scope > test scope > dependency > diff --git a/docs/sourcey/llms.txt b/docs/sourcey/llms.txt new file mode 100644 index 00000000000..17c0d5088bd --- /dev/null +++ b/docs/sourcey/llms.txt @@ -0,0 +1,31 @@ +# Testcontainers for Java Sourcey Reference + +> *Testcontainers for Java* is a Java library that supports JUnit tests, providing lightweight, throwaway instances of common databases, Selenium web browsers, or anything else that can run in a Docker container. + +## Java Guide + +- [Testcontainers for Java](/sourcey/): *Testcontainers for Java* is a Java library that supports JUnit tests, providing lightweight, throwaway instances of common databases, Selenium web browsers, or anything else that can run in a Docker container. +- [Examples](/sourcey/examples.html): Examples of different use cases provided by Testcontainers can be found below: +- [JUnit 4 Quickstart](/sourcey/quickstart/junit-4-quickstart.html): It's easy to add Testcontainers to your project - let's walk through a quick example to see how. +- [JUnit 5 Quickstart](/sourcey/quickstart/junit-5-quickstart.html): It's easy to add Testcontainers to your project - let's walk through a quick example to see how. +- [Spock Quickstart](/sourcey/quickstart/spock-quickstart.html): It's easy to add Testcontainers to your project - let's walk through a quick example to see how. +- [Creating a container](/sourcey/features/creating-container.html): Testcontainers' generic container support offers the most flexibility, and makes it easy to use virtually any container images as temporary test dependencies. For example, if you might use it to test interactions with: +- [Networking and communicating with containers](/sourcey/features/networking.html): It is common to want to connect to a container from your test process, running on the test 'host' machine. For example, you may be testing a class that needs to connect to a backend or data store container. +- [Executing commands](/sourcey/features/commands.html): By default the container will execute whatever command is specified in the image's Dockerfile. To override this, and specify a different command, use `withCommand`. For example: +- [Files and volumes](/sourcey/features/files.html): Files can be copied into the container before startup, or can be copied from the container after the container has started. +- [Waiting for containers to start or be ready](/sourcey/features/startup-and-waits.html): Ordinarily Testcontainers will wait for up to 60 seconds for the container's first mapped network port to start listening. +- [Accessing container logs](/sourcey/features/container-logs.html): It is possible to capture container output using: +- [Creating images on-the-fly](/sourcey/features/creating-images.html): In situations where there is no pre-existing Docker image, Testcontainers can create a new temporary image on-the-fly from a Dockerfile. For example, when the component under test is the Docker image itself, or when an existing base image needs to be customized for specific test(s). +- [Custom configuration](/sourcey/features/configuration.html): You can override some default properties if your environment requires that. +- [Image name substitution](/sourcey/features/image-name-substitution.html): Testcontainers supports automatic substitution of Docker image names. +- [Advanced options](/sourcey/features/advanced-options.html): To add a custom label to the container, use `withLabel`: +- [Reusable Containers (Experimental)](/sourcey/features/reuse.html): The *Reusable* feature keeps the containers running and next executions with the same container configuration will reuse it. To use it, start the container manually by calling `start()` method, do not call `stop()` method directly or indirectly via `try-with-resources` or `JUnit integration`, and enable it manually through an opt-in mechanism per environment. To reuse a container, the container configuration **must be the same**. +- [Database containers](/sourcey/modules/databases/): You might want to use Testcontainers' database support: +- [JDBC support](/sourcey/modules/databases/jdbc.html): You can obtain a temporary database in one of two ways: +- [Postgres Module](/sourcey/modules/databases/postgres.html): Testcontainers module for PostgresSQL +- [MySQL Module](/sourcey/modules/databases/mysql.html): Testcontainers module for MySQL +- [MongoDB Module](/sourcey/modules/databases/mongodb.html): The MongoDB module provides two Testcontainers for MongoDB unit testing: +- [Kafka Module](/sourcey/modules/kafka.html): Testcontainers can be used to automatically instantiate and manage Apache Kafka containers. +- [LocalStack Module](/sourcey/modules/localstack.html): Testcontainers module for LocalStack, 'a fully functional local AWS cloud stack', to develop and test your cloud and serverless apps without actually using the cloud. +- [Toxiproxy Module](/sourcey/modules/toxiproxy.html): Testcontainers module for Shopify's Toxiproxy. This TCP proxy can be used to simulate network failure conditions. +- [Jupiter / JUnit 5](/sourcey/test-framework-integration/junit-5.html): This module provides an API that is based on the JUnit Jupiter extension model. diff --git a/docs/sourcey/logo.png b/docs/sourcey/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..88961b3e3f0c0520a48e91b06e353a73fce35594 GIT binary patch literal 67366 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 AC;$Ke literal 0 HcmV?d00001 diff --git a/docs/sourcey/logo.svg b/docs/sourcey/logo.svg new file mode 100644 index 00000000000..bac0c391a59 --- /dev/null +++ b/docs/sourcey/logo.svg @@ -0,0 +1,92 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/sourcey/modules/databases/index.html b/docs/sourcey/modules/databases/index.html new file mode 100644 index 00000000000..40372e368a1 --- /dev/null +++ b/docs/sourcey/modules/databases/index.html @@ -0,0 +1,34 @@ + +Database containers - Testcontainers for Java Sourcey Reference
    Modules

    Database containers

    You might want to use Testcontainers' database support:

    Overview

    +

    You might want to use Testcontainers' database support:

    +
      +
    • Instead of H2 database for DAO unit tests that depend on database features that H2 doesn't emulate. Testcontainers is not as performant as H2, but does give you the benefit of 100% database compatibility (since it runs a real DB inside of a container).
    • +
    • Instead of a database running on the local machine or in a VM for DAO unit tests or end-to-end integration tests that need a database to be present. In this context, the benefit of Testcontainers is that the database always starts in a known state, without any contamination between test runs or on developers' local machines.
    • +
    +
    +

    Note +Of course, it's still important to have as few tests that hit the database as possible, and make good use of mocks for components higher up the stack.

    +
    +

    See JDBC and R2DBC for information on how to use Testcontainers with SQL-like databases.

    +
    \ No newline at end of file diff --git a/docs/sourcey/modules/databases/jdbc.html b/docs/sourcey/modules/databases/jdbc.html new file mode 100644 index 00000000000..a3286596514 --- /dev/null +++ b/docs/sourcey/modules/databases/jdbc.html @@ -0,0 +1,132 @@ + +JDBC support - Testcontainers for Java Sourcey Reference
    Modules

    JDBC support

    You can obtain a temporary database in one of two ways:

    You can obtain a temporary database in one of two ways:

    +
      +
    • Using a specially modified JDBC URL: after making a very simple modification to your system's JDBC URL string, Testcontainers will provide a disposable stand-in database that can be used without requiring modification to your application code.
    • +
    • JUnit @Rule/@ClassRule: this mode starts a database inside a container before your tests and tears it down afterwards.
    • +
    +

    Database containers launched via JDBC URL scheme

    +

    As long as you have Testcontainers and the appropriate JDBC driver on your classpath, you can simply modify regular JDBC connection URLs to get a fresh containerized instance of the database each time your application starts up.

    +

    N.B:

    +
      +
    • TC needs to be on your application's classpath at runtime for this to work
    • +
    • For Spring Boot (Before version 2.3.0) you need to specify the driver manually spring.datasource.driver-class-name=org.testcontainers.jdbc.ContainerDatabaseDriver
    • +
    +

    Original URL: jdbc:mysql://localhost:3306/databasename

    +

    Insert tc: after jdbc: as follows. Note that the hostname, port and database name will be ignored; you can leave these as-is or set them to any value.

    +
    +

    Note +We will use /// (host-less URIs) from now on to emphasis the unimportance of the host:port pair.
    From Testcontainers' perspective, jdbc:mysql:8.0.36://localhost:3306/databasename and jdbc:mysql:8.0.36:///databasename is the same URI.

    +

    Warning +If you're using the JDBC URL support, there is no need to instantiate an instance of the container - Testcontainers will do it automagically.

    +
    +

    JDBC URL examples

    +

    Using ClickHouse

    +

    jdbc:tc:clickhouse:18.10.3:///databasename

    +

    Using CockroachDB

    +

    jdbc:tc:cockroach:v21.2.3:///databasename

    +

    Using CrateDB

    +

    jdbc:tc:cratedb:5.2.3:///databasename

    +

    Using DB2

    +

    jdbc:tc:db2:11.5.0.0a:///databasename

    +

    Using MariaDB

    +

    jdbc:tc:mariadb:10.3.39:///databasename

    +

    Using MySQL

    +

    jdbc:tc:mysql:8.0.36:///databasename

    +

    Using MSSQL Server

    +

    jdbc:tc:sqlserver:2017-CU12:///databasename

    +

    Using OceanBase

    +

    jdbc:tc:oceanbasece:4.2.1-lts:///databasename

    +

    Using Oracle

    +

    jdbc:tc:oracle:21-slim-faststart:///databasename

    +

    Using PostGIS

    +

    jdbc:tc:postgis:9.6-2.5:///databasename

    +

    Using PostgreSQL

    +

    jdbc:tc:postgresql:9.6.8:///databasename

    +

    Using QuestDB

    +

    jdbc:tc:questdb:6.5.3:///databasename

    +

    Using TimescaleDB

    +

    jdbc:tc:timescaledb:2.1.0-pg13:///databasename

    +

    Using PGVector

    +

    jdbc:tc:pgvector:pg16:///databasename

    +

    Using TiDB

    +

    jdbc:tc:tidb:v6.1.0:///databasename

    +

    Using Timeplus

    +

    jdbc:tc:timeplus:2.3.21:///databasename

    +

    Using Trino

    +

    jdbc:tc:trino:352://localhost/memory/default

    +

    Using YugabyteDB

    +

    jdbc:tc:yugabyte:2.14.4.0-b26:///databasename

    +

    Using a classpath init script

    +

    Testcontainers can run an init script after the database container is started, but before your code is given a connection to it. The script must be on the classpath, and is referenced as follows:

    +

    jdbc:tc:mysql:8.0.36:///databasename?TC_INITSCRIPT=somepath/init_mysql.sql

    +

    This is useful if you have a fixed script for setting up database schema, etc.

    +

    Using an init script from a file

    +

    If the init script path is prefixed file:, it will be loaded from a file (relative to the working directory, which will usually be the project root).

    +

    jdbc:tc:mysql:8.0.36:///databasename?TC_INITSCRIPT=file:src/main/resources/init_mysql.sql

    +

    Using an init function

    +

    Instead of running a fixed script for DB setup, it may be useful to call a Java function that you define. This is intended to allow you to trigger database schema migration tools. To do this, add TC_INITFUNCTION to the URL as follows, passing a full path to the class name and method:

    +

    jdbc:tc:mysql:8.0.36:///databasename?TC_INITFUNCTION=org.testcontainers.jdbc.JDBCDriverTest::sampleInitFunction

    +

    The init function must be a public static method which takes a java.sql.Connection as its only parameter, e.g.

    +
    +
    + +
    +
    public class JDBCDriverTest {
    +    public static void sampleInitFunction(Connection connection) throws SQLException {
    +        // e.g. run schema setup or Flyway/liquibase/etc DB migrations here...
    +    }
    +    ...
    +

    Running container in daemon mode

    +

    By default database container is being stopped as soon as last connection is closed. There are cases when you might need to start container and keep it running till you stop it explicitly or JVM is shutdown. To do this, add TC_DAEMON parameter to the URL as follows:

    +

    jdbc:tc:mysql:8.0.36:///databasename?TC_DAEMON=true

    +

    With this parameter database container will keep running even when there's no open connections.

    +

    Running container with tmpfs options

    +

    Container can have tmpfs mounts for storing data in host memory. This is useful if you want to speed up your database tests. Be aware that the data will be lost when the container stops.

    +

    To pass this option to the container, add TC_TMPFS parameter to the URL as follows:

    +

    jdbc:tc:postgresql:9.6.8:///databasename?TC_TMPFS=/testtmpfs:rw

    +

    If you need more than one option, separate them by comma (e.g. TC_TMPFS=key:value,key1:value1&other_parameters=foo).

    +

    For more information about tmpfs mount, see the official Docker documentation.

    +

    Database container objects

    +

    In case you can't use the URL support, or need to fine-tune the container, you can instantiate it yourself.

    +

    Add a @Rule or @ClassRule to your test class, e.g.:

    +
    +
    + +
    +
    public class SimpleMySQLTest {
    +    @Rule
    +    public MySQLContainer mysql = new MySQLContainer();
    +

    Now, in your test code (or a suitable setup method), you can obtain details necessary to connect to this database:

    +
      +
    • mysql.getJdbcUrl() provides a JDBC URL your code can connect to
    • +
    • mysql.getUsername() provides the username your code should pass to the driver
    • +
    • mysql.getPassword() provides the password your code should pass to the driver
    • +
    +

    Note that if you use @Rule, you will be given an isolated container for each test method. If you use @ClassRule, you will get on isolated container for all the methods in the test class.

    +

    Examples/Tests:

    + +
    \ No newline at end of file diff --git a/docs/sourcey/modules/databases/mongodb.html b/docs/sourcey/modules/databases/mongodb.html new file mode 100644 index 00000000000..d9ac98e9fde --- /dev/null +++ b/docs/sourcey/modules/databases/mongodb.html @@ -0,0 +1,105 @@ + +MongoDB Module - Testcontainers for Java Sourcey Reference
    Modules

    MongoDB Module

    The MongoDB module provides two Testcontainers for MongoDB unit testing:

    The MongoDB module provides two Testcontainers for MongoDB unit testing:

    + +

    MongoDBContainer

    +

    Usage example

    +

    The following example shows how to create a MongoDBContainer:

    + +

    Creating a MongoDB container inside_block:creatingMongoDBContainer

    + + +

    And how to start it:

    + +

    Starting a MongoDB container inside_block:startingMongoDBContainer

    + + +
    +

    Note +To construct a multi-node MongoDB cluster, consider the mongodb-replica-set project

    +
    +

    Motivation

    +

    Implement a reusable, cross-platform, simple to install solution that doesn't depend on +fixed ports to test MongoDB transactions.

    +

    General info

    +

    MongoDB starting from version 4 supports multi-document transactions only for a replica set. +For instance, to initialize a single node replica set on fixed ports via Docker, one has to do the following:

    +
      +
    • Run a MongoDB container of version 4 and up specifying --replSet command
    • +
    • Initialize a single replica set via executing a proper command
    • +
    • Wait for the initialization to complete
    • +
    • Provide a special url for a user to employ with a MongoDB driver without specifying replicaSet
    • +
    +

    As we can see, there is a lot of operations to execute and we even haven't touched a non-fixed port approach. +That's where the MongoDBContainer might come in handy.

    +

    MongoDBAtlasLocalContainer

    +

    Usage example

    +

    The following example shows how to create a MongoDBAtlasLocalContainer:

    + +

    Creating a MongoDB Atlas Local Container inside_block:creatingAtlasLocalContainer

    + + +

    And how to start it:

    + +

    Start the Container inside_block:startingAtlasLocalContainer

    + + +

    The connection string provided by the MongoDBAtlasLocalContainer's getConnectionString() method includes the dynamically allocated port:

    + +

    Get the Connection String inside_block:getConnectionStringAtlasLocalContainer

    + + +

    e.g. mongodb://localhost:12345/?directConnection=true

    +

    References

    +

    MongoDB Atlas Local combines the MongoDB database engine with MongoT, a sidecar process for advanced searching capabilities built by MongoDB and powered by Apache Lucene.

    +

    The container (mongodb/mongodb-atlas-local) documentation can be found here.

    +

    General information about Atlas Search can be found here.

    +

    Adding this module to your project dependencies

    +

    Add the following dependency to your pom.xml/build.gradle file:

    +

    Gradle

    +
    +
    + +
    +
    testImplementation "org.testcontainers:testcontainers-mongodb:{{latest_version}}"
    +

    Maven

    +
    +
    + +
    +
    &lt;dependency&gt;
    +    &lt;groupId&gt;org.testcontainers</groupId>
    +    &lt;artifactId&gt;testcontainers-mongodb</artifactId>
    +    &lt;version&gt;{{latest_version}}</version>
    +    &lt;scope&gt;test</scope>
    +</dependency>
    +
    +

    Hint +Adding this Testcontainers library JAR will not automatically add a database driver JAR to your project. You should ensure that your project also has a suitable database driver as a dependency

    +
    + +

    Copyright (c) 2019 Konstantin Silaev silaev256@gmail.com

    +
    \ No newline at end of file diff --git a/docs/sourcey/modules/databases/mysql.html b/docs/sourcey/modules/databases/mysql.html new file mode 100644 index 00000000000..ed6f7204622 --- /dev/null +++ b/docs/sourcey/modules/databases/mysql.html @@ -0,0 +1,67 @@ + +MySQL Module - Testcontainers for Java Sourcey Reference
    Modules

    MySQL Module

    Testcontainers module for MySQL

    Testcontainers module for MySQL

    +

    Usage example

    +

    You can start a MySQL container instance from any Java application by using:

    + +

    Container definition inside_block:container

    + + +

    See Database containers for documentation and usage that is common to all relational database container types.

    +

    Testcontainers JDBC URL

    +

    jdbc:tc:mysql:8.0.36:///databasename

    +

    See JDBC for documentation.

    +

    Overriding MySQL my.cnf settings

    +

    For MySQL databases, it is possible to override configuration settings using resources on the classpath. Assuming somepath/mysql_conf_override +is a directory on the classpath containing .cnf files, the following URL can be used:

    +

    jdbc:tc:mysql:8.0.36://hostname/databasename?TC_MY_CNF=somepath/mysql_conf_override

    +

    Any .cnf files in this classpath directory will be mapped into the database container's /etc/mysql/conf.d directory, +and will be able to override server settings when the container starts.

    +

    MySQL root user password

    +

    If no custom password is specified, the container will use the default user password test for the root user as well. +When you specify a custom password for the database user, +this will also act as the password of the MySQL root user automatically.

    +

    Adding this module to your project dependencies

    +

    Add the following dependency to your pom.xml/build.gradle file:

    +

    Gradle

    +
    +
    + +
    +
    testImplementation "org.testcontainers:testcontainers-mysql:{{latest_version}}"
    +

    Maven

    +
    +
    + +
    +
    &lt;dependency&gt;
    +    &lt;groupId&gt;org.testcontainers</groupId>
    +    &lt;artifactId&gt;testcontainers-mysql</artifactId>
    +    &lt;version&gt;{{latest_version}}</version>
    +    &lt;scope&gt;test</scope>
    +</dependency>
    +
    +

    Hint +Adding this Testcontainers library JAR will not automatically add a database driver JAR to your project. You should ensure that your project also has a suitable database driver as a dependency.

    +
    +
    \ No newline at end of file diff --git a/docs/sourcey/modules/databases/postgres.html b/docs/sourcey/modules/databases/postgres.html new file mode 100644 index 00000000000..68c46ac39ce --- /dev/null +++ b/docs/sourcey/modules/databases/postgres.html @@ -0,0 +1,85 @@ + +Postgres Module - Testcontainers for Java Sourcey Reference
    Modules

    Postgres Module

    Testcontainers module for PostgresSQL

    Testcontainers module for PostgresSQL

    +

    Usage example

    +

    You can start a PostgreSQL container instance from any Java application by using:

    + +

    Container creation inside_block:container

    + + +

    See Database containers for documentation and usage that is common to all relational database container types.

    +

    Testcontainers JDBC URL

    +
      +
    • PostgreSQL: jdbc:tc:postgresql:9.6.8:///databasename
    • +
    • PostGIS: jdbc:tc:postgis:9.6-2.5:///databasename
    • +
    • TimescaleDB: jdbc:tc:timescaledb:2.1.0-pg13:///databasename
    • +
    • PGvector: jdbc:tc:pgvector:pg16:///databasename
    • +
    +

    See JDBC for documentation.

    +

    Compatible images

    +

    PostgreSQLContainer can also be used with the following images:

    + + +

    Using pgvector inside_block:pgvectorContainer

    + + + + +

    Using PostGIS inside_block:postgisContainer

    + + + + +

    Using TimescaleDB inside_block:timescaledbContainer

    + + +

    Adding this module to your project dependencies

    +

    Add the following dependency to your pom.xml/build.gradle file:

    +

    Gradle

    +
    +
    + +
    +
    testImplementation "org.testcontainers:testcontainers-postgresql:{{latest_version}}"
    +

    Maven

    +
    +
    + +
    +
    &lt;dependency&gt;
    +    &lt;groupId&gt;org.testcontainers</groupId>
    +    &lt;artifactId&gt;testcontainers-postgresql</artifactId>
    +    &lt;version&gt;{{latest_version}}</version>
    +    &lt;scope&gt;test</scope>
    +</dependency>
    +
    +

    Hint +Adding this Testcontainers library JAR will not automatically add a database driver JAR to your project. You should ensure that your project also has a suitable database driver as a dependency.

    +
    +
    \ No newline at end of file diff --git a/docs/sourcey/modules/kafka.html b/docs/sourcey/modules/kafka.html new file mode 100644 index 00000000000..0fc1876dc0f --- /dev/null +++ b/docs/sourcey/modules/kafka.html @@ -0,0 +1,110 @@ + +Kafka Module - Testcontainers for Java Sourcey Reference
    Modules

    Kafka Module

    Testcontainers can be used to automatically instantiate and manage Apache Kafka containers.

    Testcontainers can be used to automatically instantiate and manage Apache Kafka containers.

    +

    Currently, two different Kafka images are supported:

    + +
    +

    Note +org.testcontainers.containers.KafkaContainer is deprecated. +Please use org.testcontainers.kafka.ConfluentKafkaContainer or org.testcontainers.kafka.KafkaContainer instead, depending on the used image.

    +
    +

    Benefits

    +
      +
    • Running a single node Kafka installation with just one line of code
    • +
    • No need to manage external Zookeeper installation, required by Kafka.
    • +
    +

    Example

    +

    Using org.testcontainers.kafka.KafkaContainer

    +

    Create a KafkaContainer to use it in your tests:

    + +

    Creating a KafkaContainer inside_block:constructorWithVersion

    + + +

    Now your tests or any other process running on your machine can get access to running Kafka broker by using the following bootstrap server location:

    + +

    Bootstrap Servers inside_block:getBootstrapServers

    + + +

    Using org.testcontainers.kafka.ConfluentKafkaContainer

    +
    +

    Note +Compatible with confluentinc/cp-kafka images version 7.4.0 and later.

    +
    +

    Create a ConfluentKafkaContainer to use it in your tests:

    + +

    Creating a ConfluentKafkaContainer inside_block:constructorWithVersion

    + + +

    Options

    +

    Using Kraft mode

    +
    +

    Note +Only available for org.testcontainers.containers.KafkaContainer

    +
    +

    KRaft mode was declared production ready in 3.3.1 (confluentinc/cp-kafka:7.3.x)

    + +

    Kraft mode inside_block:withKraftMode

    + + +

    See the versions interoperability matrix for more details.

    +

    Register listeners

    +

    There are scenarios where additional listeners are needed because the consumer/producer can be in another +container in the same network or a different process where the port to connect differs from the default exposed port. E.g Toxiproxy.

    + +

    Register additional listener inside_block:registerListener

    + + +

    Container defined in the same network:

    + +

    Create kcat container inside_block:createKCatContainer

    + + +

    Client using the new registered listener:

    + +

    Produce/Consume via new listener inside_block:produceConsumeMessage

    + + +

    Adding this module to your project dependencies

    +

    Add the following dependency to your pom.xml/build.gradle file:

    +

    Gradle

    +
    +
    + +
    +
    testImplementation "org.testcontainers:testcontainers-kafka:{{latest_version}}"
    +

    Maven

    +
    +
    + +
    +
    &lt;dependency&gt;
    +    &lt;groupId&gt;org.testcontainers</groupId>
    +    &lt;artifactId&gt;testcontainers-kafka</artifactId>
    +    &lt;version&gt;{{latest_version}}</version>
    +    &lt;scope&gt;test</scope>
    +</dependency>
    +
    \ No newline at end of file diff --git a/docs/sourcey/modules/localstack.html b/docs/sourcey/modules/localstack.html new file mode 100644 index 00000000000..58bfbbb8a83 --- /dev/null +++ b/docs/sourcey/modules/localstack.html @@ -0,0 +1,62 @@ + +LocalStack Module - Testcontainers for Java Sourcey Reference
    Modules

    LocalStack Module

    Testcontainers module for LocalStack, 'a fully functional local AWS cloud stack', to develop and test your cloud and serverless apps without actually using the cloud.

    Testcontainers module for LocalStack, 'a fully functional local AWS cloud stack', to develop and test your cloud and serverless apps without actually using the cloud.

    +

    Usage example

    +

    You can start a LocalStack container instance from any Java application by using:

    + +

    Container creation inside_block:container

    + + +

    Environment variables listed in the LocalStack configuration documentation may be used to customize LocalStack's configuration. +Use the .withEnv(key, value) method on LocalStackContainer to apply configuration settings.

    +
    +

    Note +Starting March 23, 2026, localstack/localstack requires authentication via a LOCALSTACK_AUTH_TOKEN environment variable. Without it, the container will fail to start.

    +

    Use .withEnv("LOCALSTACK_AUTH_TOKEN", System.getenv("LOCALSTACK_AUTH_TOKEN")) to pass the token. +See the LocalStack blog post for more details.

    +
    +

    Creating a client using AWS SDK

    + +

    AWS SDK V2 inside_block:with_aws_sdk_v2

    + + +

    Adding this module to your project dependencies

    +

    Add the following dependency to your pom.xml/build.gradle file:

    +

    Gradle

    +
    +
    + +
    +
    testImplementation "org.testcontainers:testcontainers-localstack:{{latest_version}}"
    +

    Maven

    +
    +
    + +
    +
    &lt;dependency&gt;
    +    &lt;groupId&gt;org.testcontainers</groupId>
    +    &lt;artifactId&gt;testcontainers-localstack</artifactId>
    +    &lt;version&gt;{{latest_version}}</version>
    +    &lt;scope&gt;test</scope>
    +</dependency>
    +
    \ No newline at end of file diff --git a/docs/sourcey/modules/toxiproxy.html b/docs/sourcey/modules/toxiproxy.html new file mode 100644 index 00000000000..b28c9d8a360 --- /dev/null +++ b/docs/sourcey/modules/toxiproxy.html @@ -0,0 +1,98 @@ + +Toxiproxy Module - Testcontainers for Java Sourcey Reference
    Modules

    Toxiproxy Module

    Testcontainers module for Shopify's Toxiproxy. This TCP proxy can be used to simulate network failure conditions.

    Testcontainers module for Shopify's Toxiproxy. +This TCP proxy can be used to simulate network failure conditions.

    +

    You can simulate network failures:

    +
      +
    • between Java code and containers, ideal for testing resilience features of client code
    • +
    • between containers, for testing resilience and emergent behaviour of multi-container systems
    • +
    • if desired, between Java code/containers and external resources (non-Dockerized!), for scenarios where not all dependencies can be/have been dockerized
    • +
    +

    Testcontainers Toxiproxy support allows resilience features to be easily verified as part of isolated dev/CI testing. This allows earlier testing of resilience features, and broader sets of failure conditions to be covered.

    +

    Usage example

    +

    A Toxiproxy container can be placed in between test code and a container, or in between containers. +In either scenario, it is necessary to create a ToxiproxyContainer instance on the same Docker network, as follows:

    + +

    Creating a Toxiproxy container inside_block:creatingProxy

    + + +

    Next, it is necessary to instruct Toxiproxy to start proxying connections. +Each ToxiproxyContainer can proxy to many target containers if necessary.

    +

    We do this as follows:

    + +

    Starting proxying connections to a target container inside_block:obtainProxyObject

    + + +

    To establish a connection from the test code (on the host machine) to the target container via Toxiproxy, we obtain Toxiproxy's proxy host IP and port:

    + +

    Obtaining proxied host and port inside_block:obtainProxiedHostAndPortForHostMachine

    + + +

    Code under test should connect to this proxied host IP and port.

    +
    +

    Note +Currently, ToxiProxyContainer will reserve 31 ports, starting at 8666.

    +
    +

    Other containers should connect to this proxied host and port.

    +

    Having done this, it is possible to trigger failure conditions ('Toxics') through the proxy.toxics() object:

    +
      +
    • bandwidth - Limit a connection to a maximum number of kilobytes per second.
    • +
    • latency - Add a delay to all data going through the proxy. The delay is equal to latency +/- jitter.
    • +
    • slicer - Slices TCP data up into small bits, optionally adding a delay between each sliced "packet".
    • +
    • slowClose - Delay the TCP socket from closing until delay milliseconds has elapsed.
    • +
    • timeout - Stops all data from getting through, and closes the connection after timeout. If timeout is 0, the connection won't close, and data will be delayed until the toxic is removed.
    • +
    • limitData - Closes connection when transmitted data exceeded limit.
    • +
    +

    Please see the Toxiproxy documentation for full details on the available Toxics.

    +

    As one example, we can introduce latency and random jitter to proxied connections as follows:

    + +

    Adding latency to a connection inside_block:addingLatency

    + + +

    Additionally we can disable the proxy to simulate a complete interruption to the network connection:

    + +

    Cutting a connection inside_block:disableProxy

    + + +

    Adding this module to your project dependencies

    +

    Add the following dependency to your pom.xml/build.gradle file:

    +

    Gradle

    +
    +
    + +
    +
    testImplementation "org.testcontainers:testcontainers-toxiproxy:{{latest_version}}"
    +

    Maven

    +
    +
    + +
    +
    &lt;dependency&gt;
    +    &lt;groupId&gt;org.testcontainers</groupId>
    +    &lt;artifactId&gt;testcontainers-toxiproxy</artifactId>
    +    &lt;version&gt;{{latest_version}}</version>
    +    &lt;scope&gt;test</scope>
    +</dependency>
    +

    Acknowledgements

    +

    This module was inspired by a hotels.com blog post.

    +
    \ No newline at end of file diff --git a/docs/sourcey/modules_logos/hivemq-module.png b/docs/sourcey/modules_logos/hivemq-module.png new file mode 100644 index 0000000000000000000000000000000000000000..55c0ee1644ae05a5ff5b36f90ebdb1006b296f42 GIT binary patch literal 165340 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ⅈLGoj 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 E0rq9^#Q*>R literal 0 HcmV?d00001 diff --git a/docs/sourcey/quickstart/junit-4-quickstart.html b/docs/sourcey/quickstart/junit-4-quickstart.html new file mode 100644 index 00000000000..a1913f770bc --- /dev/null +++ b/docs/sourcey/quickstart/junit-4-quickstart.html @@ -0,0 +1,92 @@ + +JUnit 4 Quickstart - Testcontainers for Java Sourcey Reference
    Quickstart

    JUnit 4 Quickstart

    It's easy to add Testcontainers to your project - let's walk through a quick example to see how.

    It's easy to add Testcontainers to your project - let's walk through a quick example to see how.

    +

    Let's imagine we have a simple program that has a dependency on Redis, and we want to add some tests for it. +In our imaginary program, there is a RedisBackedCache class which stores data in Redis.

    +

    You can see an example test that could have been written for it (without using Testcontainers):

    + +

    Pre-Testcontainers test code block:RedisBackedCacheIntTestStep0

    + + +

    Notice that the existing test has a problem - it's relying on a local installation of Redis, which is a red flag for test reliability. +This may work if we were sure that every developer and CI machine had Redis installed, but would fail otherwise. +We might also have problems if we attempted to run tests in parallel, such as state bleeding between tests, or port clashes.

    +

    Let's start from here, and see how to improve the test with Testcontainers:

    +

    1. Add Testcontainers as a test-scoped dependency

    +

    First, add Testcontainers as a dependency as follows:

    +

    Gradle

    +
    +
    + +
    +
    testImplementation "org.testcontainers:testcontainers:{{latest_version}}"
    +

    Maven

    +
    +
    + +
    +
    &lt;dependency&gt;
    +    &lt;groupId&gt;org.testcontainers</groupId>
    +    &lt;artifactId&gt;testcontainers</artifactId>
    +    &lt;version&gt;{{latest_version}}</version>
    +    &lt;scope&gt;test</scope>
    +</dependency>
    +

    2. Get Testcontainers to run a Redis container during our tests

    +

    Simply add the following to the body of our test class:

    + +

    JUnit 4 Rule inside_block:rule

    + + +

    The @Rule annotation tells JUnit to notify this field about various events in the test lifecycle. +In this case, our rule object is a Testcontainers GenericContainer, configured to use a specific Redis image from Docker Hub, and configured to expose a port.

    +

    If we run our test as-is, then regardless of the actual test outcome, we'll see logs showing us that Testcontainers:

    +
      +
    • was activated before our test method ran
    • +
    • discovered and quickly tested our local Docker setup
    • +
    • pulled the image if necessary
    • +
    • started a new container and waited for it to be ready
    • +
    • shut down and deleted the container after the test
    • +
    +

    3. Make sure our code can talk to the container

    +

    Before Testcontainers, we might have hardcoded an address like localhost:6379 into our tests.

    +

    Testcontainers uses randomized ports for each container it starts, but makes it easy to obtain the actual port at runtime. +We can do this in our test setUp method, to set up our component under test:

    + +

    Obtaining a mapped port inside_block:setUp

    + + +
    +

    Tip +Notice that we also ask Testcontainers for the container's actual address with redis.getHost();, +rather than hard-coding localhost. localhost may work in some environments but not others - for example it may +not work on your current or future CI environment. As such, avoid hard-coding the address, and use +getHost() instead.

    +
    +

    4. Run the tests!

    +

    That's it!

    +

    Let's look at our complete test class to see how little we had to add to get up and running with Testcontainers:

    + +

    RedisBackedCacheIntTest block:RedisBackedCacheIntTest

    + + +
    \ No newline at end of file diff --git a/docs/sourcey/quickstart/junit-5-quickstart.html b/docs/sourcey/quickstart/junit-5-quickstart.html new file mode 100644 index 00000000000..7f9fe8962b3 --- /dev/null +++ b/docs/sourcey/quickstart/junit-5-quickstart.html @@ -0,0 +1,114 @@ + +JUnit 5 Quickstart - Testcontainers for Java Sourcey Reference
    Quickstart

    JUnit 5 Quickstart

    It's easy to add Testcontainers to your project - let's walk through a quick example to see how.

    It's easy to add Testcontainers to your project - let's walk through a quick example to see how.

    +

    Let's imagine we have a simple program that has a dependency on Redis, and we want to add some tests for it. +In our imaginary program, there is a RedisBackedCache class which stores data in Redis.

    +

    You can see an example test that could have been written for it (without using Testcontainers):

    + +

    Pre-Testcontainers test code block:RedisBackedCacheIntTestStep0

    + + +

    Notice that the existing test has a problem - it's relying on a local installation of Redis, which is a red flag for test reliability. +This may work if we were sure that every developer and CI machine had Redis installed, but would fail otherwise. +We might also have problems if we attempted to run tests in parallel, such as state bleeding between tests, or port clashes.

    +

    Let's start from here, and see how to improve the test with Testcontainers:

    +

    1. Add Testcontainers as a test-scoped dependency

    +

    First, add Testcontainers as a dependency as follows:

    +

    Gradle

    +
    +
    + +
    +
    testImplementation "org.junit.jupiter:junit-jupiter:5.8.1"
    +testImplementation "org.testcontainers:testcontainers:{{latest_version}}"
    +testImplementation "org.testcontainers:testcontainers-junit-jupiter:{{latest_version}}"
    +

    Maven

    +
    +
    + +
    +
    &lt;dependency&gt;
    +    &lt;groupId&gt;org.junit.jupiter</groupId>
    +    &lt;artifactId&gt;junit-jupiter</artifactId>
    +    &lt;version&gt;5.8.1</version>
    +    &lt;scope&gt;test</scope>
    +</dependency>
    +&lt;dependency&gt;
    +    &lt;groupId&gt;org.testcontainers</groupId>
    +    &lt;artifactId&gt;testcontainers</artifactId>
    +    &lt;version&gt;{{latest_version}}</version>
    +    &lt;scope&gt;test</scope>
    +</dependency>
    +&lt;dependency&gt;
    +    &lt;groupId&gt;org.testcontainers</groupId>
    +    &lt;artifactId&gt;testcontainers-junit-jupiter</artifactId>
    +    &lt;version&gt;{{latest_version}}</version>
    +    &lt;scope&gt;test</scope>
    +</dependency>
    +

    2. Get Testcontainers to run a Redis container during our tests

    +

    First, you'll need to annotate the test class with @Testcontainers. Furthermore, add the following to the body of our test class:

    + +

    JUnit 5 Rule inside_block:container

    + + +

    The @Container annotation tells JUnit to notify this field about various events in the test lifecycle. +In this case, our rule object is a Testcontainers GenericContainer, configured to use a specific Redis image from Docker Hub, and configured to expose a port.

    +

    If we run our test as-is, then regardless of the actual test outcome, we'll see logs showing us that Testcontainers:

    +
      +
    • was activated before our test method ran
    • +
    • discovered and quickly tested our local Docker setup
    • +
    • pulled the image if necessary
    • +
    • started a new container and waited for it to be ready
    • +
    • shut down and deleted the container after the test
    • +
    +

    3. Make sure our code can talk to the container

    +

    Before Testcontainers, we might have hardcoded an address like localhost:6379 into our tests.

    +

    Testcontainers uses randomized ports for each container it starts, but makes it easy to obtain the actual port at runtime. +We can do this in our test setUp method, to set up our component under test:

    + +

    Obtaining a mapped port inside_block:setUp

    + + +
    +

    Tip +Notice that we also ask Testcontainers for the container's actual address with redis.getHost();, +rather than hard-coding localhost. localhost may work in some environments but not others - for example it may +not work on your current or future CI environment. As such, avoid hard-coding the address, and use +getHost() instead.

    +
    +

    4. Additional attributes

    +

    Additional attributes are available for the @Testcontainers annotation. +Those attributes can be helpful when:

    +
      +
    • Tests should be skipped instead of failing because Docker is unavailable in the +current environment. Set disabledWithoutDocker to true.
    • +
    • Enable parallel container initialization instead of sequential (by default). Set parallel to true.
    • +
    +

    5. Run the tests!

    +

    That's it!

    +

    Let's look at our complete test class to see how little we had to add to get up and running with Testcontainers:

    + +

    RedisBackedCacheIntTest inside_block:class

    + + +
    \ No newline at end of file diff --git a/docs/sourcey/quickstart/spock-quickstart.html b/docs/sourcey/quickstart/spock-quickstart.html new file mode 100644 index 00000000000..239d87a66ba --- /dev/null +++ b/docs/sourcey/quickstart/spock-quickstart.html @@ -0,0 +1,98 @@ + +Spock Quickstart - Testcontainers for Java Sourcey Reference
    Quickstart

    Spock Quickstart

    It's easy to add Testcontainers to your project - let's walk through a quick example to see how.

    It's easy to add Testcontainers to your project - let's walk through a quick example to see how.

    +

    Let's imagine we have a simple program that has a dependency on Redis, and we want to add some tests for it. +In our imaginary program, there is a RedisBackedCache class which stores data in Redis.

    +

    You can see an example test that could have been written for it (without using Testcontainers):

    + +

    Pre-Testcontainers test code block:RedisBackedCacheIntTestStep0

    + + +

    Notice that the existing test has a problem - it's relying on a local installation of Redis, which is a red flag for test reliability. +This may work if we were sure that every developer and CI machine had Redis installed, but would fail otherwise. +We might also have problems if we attempted to run tests in parallel, such as state bleeding between tests, or port clashes.

    +

    Let's start from here, and see how to improve the test with Testcontainers:

    +

    1. Add Testcontainers as a test-scoped dependency

    +

    First, add Testcontainers as a dependency as follows:

    +

    Gradle

    +
    +
    + +
    +
    testImplementation "org.testcontainers:testcontainers-spock:{{latest_version}}"
    +

    Maven

    +
    +
    + +
    +
    &lt;dependency&gt;
    +    &lt;groupId&gt;org.testcontainers</groupId>
    +    &lt;artifactId&gt;testcontainers-spock</artifactId>
    +    &lt;version&gt;{{latest_version}}</version>
    +    &lt;scope&gt;test</scope>
    +</dependency>
    +

    2. Get Testcontainers to run a Redis container during our tests

    +

    Annotate the Spock specification class with the Testcontainers extension:

    +

    Spock Testcontainers annotation

    +
    +
    + +
    +
    @org.testcontainers.spock.Testcontainers
    +class RedisBackedCacheIntTest extends Specification {
    +

    And add the following field to the body of our test class:

    + +

    Spock Testcontainers init inside_block:init

    + + +

    This tells Spock to start a Testcontainers GenericContainer, configured to use a specific Redis image from Docker Hub, and configured to expose a port.

    +

    If we run our test as-is, then regardless of the actual test outcome, we'll see logs showing us that Testcontainers:

    +
      +
    • was activated before our test method ran
    • +
    • discovered and quickly tested our local Docker setup
    • +
    • pulled the image if necessary
    • +
    • started a new container and waited for it to be ready
    • +
    • shut down and deleted the container after the test
    • +
    +

    3. Make sure our code can talk to the container

    +

    Before Testcontainers, we might have hardcoded an address like localhost:6379 into our tests.

    +

    Testcontainers uses randomized ports for each container it starts, but makes it easy to obtain the actual port at runtime. +We can do this in our test setup method, to set up our component under test:

    + +

    Obtaining a mapped port inside_block:setup

    + + +
    +

    Tip +Notice that we also ask Testcontainers for the container's actual address with redis.containerIpAddress, +rather than hard-coding localhost. localhost may work in some environments but not others - for example it may +not work on your current or future CI environment. As such, avoid hard-coding the address, and use +containerIpAddress instead.

    +
    +

    4. Run the tests!

    +

    That's it!

    +

    Let's look at our complete test class to see how little we had to add to get up and running with Testcontainers:

    + +

    RedisBackedCacheIntTest block:complete

    + +
    \ No newline at end of file diff --git a/docs/sourcey/search-index.json b/docs/sourcey/search-index.json new file mode 100644 index 00000000000..7763f94d128 --- /dev/null +++ b/docs/sourcey/search-index.json @@ -0,0 +1 @@ +[{"title":"Testcontainers for Java","content":"*Testcontainers for Java* is a Java library that supports JUnit tests, providing lightweight, throwaway instances of common databases, Selenium web browsers, or anything else that can run in a Docker container.","url":"/sourcey/","tab":"Java Guide","category":"Pages"},{"title":"About Testcontainers for Java","content":"Testcontainers for Java - About Testcontainers for Java","url":"/sourcey/#about-testcontainers-for-java","tab":"Java Guide","category":"Sections"},{"title":"Prerequisites","content":"Testcontainers for Java - Prerequisites","url":"/sourcey/#prerequisites","tab":"Java Guide","category":"Sections"},{"title":"Maven dependencies","content":"Testcontainers for Java - Maven dependencies","url":"/sourcey/#maven-dependencies","tab":"Java Guide","category":"Sections"},{"title":"Managing versions for multiple Testcontainers dependencies","content":"Testcontainers for Java - Managing versions for multiple Testcontainers dependencies","url":"/sourcey/#managing-versions-for-multiple-testcontainers-dependencies","tab":"Java Guide","category":"Sections"},{"title":"Sponsors","content":"Testcontainers for Java - Sponsors","url":"/sourcey/#sponsors","tab":"Java Guide","category":"Sections"},{"title":"Bronze sponsors","content":"Testcontainers for Java - Bronze sponsors","url":"/sourcey/#bronze-sponsors","tab":"Java Guide","category":"Sections"},{"title":"Donors","content":"Testcontainers for Java - Donors","url":"/sourcey/#donors","tab":"Java Guide","category":"Sections"},{"title":"Backers","content":"Testcontainers for Java - Backers","url":"/sourcey/#backers","tab":"Java Guide","category":"Sections"},{"title":"Who is using Testcontainers?","content":"Testcontainers for Java - Who is using Testcontainers?","url":"/sourcey/#who-is-using-testcontainers","tab":"Java Guide","category":"Sections"},{"title":"License","content":"Testcontainers for Java - License","url":"/sourcey/#license","tab":"Java Guide","category":"Sections"},{"title":"Attributions","content":"Testcontainers for Java - Attributions","url":"/sourcey/#attributions","tab":"Java Guide","category":"Sections"},{"title":"Copyright","content":"Testcontainers for Java - Copyright","url":"/sourcey/#copyright","tab":"Java Guide","category":"Sections"},{"title":"Examples","content":"Examples of different use cases provided by Testcontainers can be found below:","url":"/sourcey/examples.html","tab":"Java Guide","category":"Pages"},{"title":"JUnit 4 Quickstart","content":"It's easy to add Testcontainers to your project - let's walk through a quick example to see how.","url":"/sourcey/quickstart/junit-4-quickstart.html","tab":"Java Guide","category":"Pages"},{"title":"1. Add Testcontainers as a test-scoped dependency","content":"JUnit 4 Quickstart - 1. Add Testcontainers as a test-scoped dependency","url":"/sourcey/quickstart/junit-4-quickstart.html#1-add-testcontainers-as-a-test-scoped-dependency","tab":"Java Guide","category":"Sections"},{"title":"2. Get Testcontainers to run a Redis container during our tests","content":"JUnit 4 Quickstart - 2. Get Testcontainers to run a Redis container during our tests","url":"/sourcey/quickstart/junit-4-quickstart.html#2-get-testcontainers-to-run-a-redis-container-during-our-tests","tab":"Java Guide","category":"Sections"},{"title":"3. Make sure our code can talk to the container","content":"JUnit 4 Quickstart - 3. Make sure our code can talk to the container","url":"/sourcey/quickstart/junit-4-quickstart.html#3-make-sure-our-code-can-talk-to-the-container","tab":"Java Guide","category":"Sections"},{"title":"4. Run the tests!","content":"JUnit 4 Quickstart - 4. Run the tests!","url":"/sourcey/quickstart/junit-4-quickstart.html#4-run-the-tests","tab":"Java Guide","category":"Sections"},{"title":"JUnit 5 Quickstart","content":"It's easy to add Testcontainers to your project - let's walk through a quick example to see how.","url":"/sourcey/quickstart/junit-5-quickstart.html","tab":"Java Guide","category":"Pages"},{"title":"1. Add Testcontainers as a test-scoped dependency","content":"JUnit 5 Quickstart - 1. Add Testcontainers as a test-scoped dependency","url":"/sourcey/quickstart/junit-5-quickstart.html#1-add-testcontainers-as-a-test-scoped-dependency","tab":"Java Guide","category":"Sections"},{"title":"2. Get Testcontainers to run a Redis container during our tests","content":"JUnit 5 Quickstart - 2. Get Testcontainers to run a Redis container during our tests","url":"/sourcey/quickstart/junit-5-quickstart.html#2-get-testcontainers-to-run-a-redis-container-during-our-tests","tab":"Java Guide","category":"Sections"},{"title":"3. Make sure our code can talk to the container","content":"JUnit 5 Quickstart - 3. Make sure our code can talk to the container","url":"/sourcey/quickstart/junit-5-quickstart.html#3-make-sure-our-code-can-talk-to-the-container","tab":"Java Guide","category":"Sections"},{"title":"4. Additional attributes","content":"JUnit 5 Quickstart - 4. Additional attributes","url":"/sourcey/quickstart/junit-5-quickstart.html#4-additional-attributes","tab":"Java Guide","category":"Sections"},{"title":"5. Run the tests!","content":"JUnit 5 Quickstart - 5. Run the tests!","url":"/sourcey/quickstart/junit-5-quickstart.html#5-run-the-tests","tab":"Java Guide","category":"Sections"},{"title":"Spock Quickstart","content":"It's easy to add Testcontainers to your project - let's walk through a quick example to see how.","url":"/sourcey/quickstart/spock-quickstart.html","tab":"Java Guide","category":"Pages"},{"title":"1. Add Testcontainers as a test-scoped dependency","content":"Spock Quickstart - 1. Add Testcontainers as a test-scoped dependency","url":"/sourcey/quickstart/spock-quickstart.html#1-add-testcontainers-as-a-test-scoped-dependency","tab":"Java Guide","category":"Sections"},{"title":"2. Get Testcontainers to run a Redis container during our tests","content":"Spock Quickstart - 2. Get Testcontainers to run a Redis container during our tests","url":"/sourcey/quickstart/spock-quickstart.html#2-get-testcontainers-to-run-a-redis-container-during-our-tests","tab":"Java Guide","category":"Sections"},{"title":"3. Make sure our code can talk to the container","content":"Spock Quickstart - 3. Make sure our code can talk to the container","url":"/sourcey/quickstart/spock-quickstart.html#3-make-sure-our-code-can-talk-to-the-container","tab":"Java Guide","category":"Sections"},{"title":"4. Run the tests!","content":"Spock Quickstart - 4. Run the tests!","url":"/sourcey/quickstart/spock-quickstart.html#4-run-the-tests","tab":"Java Guide","category":"Sections"},{"title":"Creating a container","content":"Testcontainers' generic container support offers the most flexibility, and makes it easy to use virtually any container images as temporary test dependencies. For example, if you might use it to test interactions with:","url":"/sourcey/features/creating-container.html","tab":"Java Guide","category":"Pages"},{"title":"Creating a generic container based on an image","content":"Creating a container - Creating a generic container based on an image","url":"/sourcey/features/creating-container.html#creating-a-generic-container-based-on-an-image","tab":"Java Guide","category":"Sections"},{"title":"Specifying an image","content":"Creating a container - Specifying an image","url":"/sourcey/features/creating-container.html#specifying-an-image","tab":"Java Guide","category":"Sections"},{"title":"Examples","content":"Creating a container - Examples","url":"/sourcey/features/creating-container.html#examples","tab":"Java Guide","category":"Sections"},{"title":"Networking and communicating with containers","content":"It is common to want to connect to a container from your test process, running on the test 'host' machine. For example, you may be testing a class that needs to connect to a backend or data store container.","url":"/sourcey/features/networking.html","tab":"Java Guide","category":"Pages"},{"title":"Exposing container ports to the host","content":"Networking and communicating with containers - Exposing container ports to the host","url":"/sourcey/features/networking.html#exposing-container-ports-to-the-host","tab":"Java Guide","category":"Sections"},{"title":"Getting the container host","content":"Networking and communicating with containers - Getting the container host","url":"/sourcey/features/networking.html#getting-the-container-host","tab":"Java Guide","category":"Sections"},{"title":"Exposing host ports to the container","content":"Networking and communicating with containers - Exposing host ports to the container","url":"/sourcey/features/networking.html#exposing-host-ports-to-the-container","tab":"Java Guide","category":"Sections"},{"title":"Advanced networking","content":"Networking and communicating with containers - Advanced networking","url":"/sourcey/features/networking.html#advanced-networking","tab":"Java Guide","category":"Sections"},{"title":"Executing commands","content":"By default the container will execute whatever command is specified in the image's Dockerfile. To override this, and specify a different command, use `withCommand`. For example:","url":"/sourcey/features/commands.html","tab":"Java Guide","category":"Pages"},{"title":"Container startup command","content":"Executing commands - Container startup command","url":"/sourcey/features/commands.html#container-startup-command","tab":"Java Guide","category":"Sections"},{"title":"Executing a command","content":"Executing commands - Executing a command","url":"/sourcey/features/commands.html#executing-a-command","tab":"Java Guide","category":"Sections"},{"title":"Environment variables","content":"Executing commands - Environment variables","url":"/sourcey/features/commands.html#environment-variables","tab":"Java Guide","category":"Sections"},{"title":"Files and volumes","content":"Files can be copied into the container before startup, or can be copied from the container after the container has started.","url":"/sourcey/features/files.html","tab":"Java Guide","category":"Pages"},{"title":"Copying files","content":"Files and volumes - Copying files","url":"/sourcey/features/files.html#copying-files","tab":"Java Guide","category":"Sections"},{"title":"Copying to a container before startup","content":"Files and volumes - Copying to a container before startup","url":"/sourcey/features/files.html#copying-to-a-container-before-startup","tab":"Java Guide","category":"Sections"},{"title":"Copying a file from a running container","content":"Files and volumes - Copying a file from a running container","url":"/sourcey/features/files.html#copying-a-file-from-a-running-container","tab":"Java Guide","category":"Sections"},{"title":"Waiting for containers to start or be ready","content":"Ordinarily Testcontainers will wait for up to 60 seconds for the container's first mapped network port to start listening.","url":"/sourcey/features/startup-and-waits.html","tab":"Java Guide","category":"Pages"},{"title":"Wait Strategies","content":"Waiting for containers to start or be ready - Wait Strategies","url":"/sourcey/features/startup-and-waits.html#wait-strategies","tab":"Java Guide","category":"Sections"},{"title":"HTTP Wait strategy examples","content":"Waiting for containers to start or be ready - HTTP Wait strategy examples","url":"/sourcey/features/startup-and-waits.html#http-wait-strategy-examples","tab":"Java Guide","category":"Sections"},{"title":"Healthcheck Wait strategy examples","content":"Waiting for containers to start or be ready - Healthcheck Wait strategy examples","url":"/sourcey/features/startup-and-waits.html#healthcheck-wait-strategy-examples","tab":"Java Guide","category":"Sections"},{"title":"Log output Wait Strategy","content":"Waiting for containers to start or be ready - Log output Wait Strategy","url":"/sourcey/features/startup-and-waits.html#log-output-wait-strategy","tab":"Java Guide","category":"Sections"},{"title":"Other Wait Strategies","content":"Waiting for containers to start or be ready - Other Wait Strategies","url":"/sourcey/features/startup-and-waits.html#other-wait-strategies","tab":"Java Guide","category":"Sections"},{"title":"Startup check Strategies","content":"Waiting for containers to start or be ready - Startup check Strategies","url":"/sourcey/features/startup-and-waits.html#startup-check-strategies","tab":"Java Guide","category":"Sections"},{"title":"Running startup strategy example","content":"Waiting for containers to start or be ready - Running startup strategy example","url":"/sourcey/features/startup-and-waits.html#running-startup-strategy-example","tab":"Java Guide","category":"Sections"},{"title":"One shot startup strategy example","content":"Waiting for containers to start or be ready - One shot startup strategy example","url":"/sourcey/features/startup-and-waits.html#one-shot-startup-strategy-example","tab":"Java Guide","category":"Sections"},{"title":"Indefinite one shot startup strategy example","content":"Waiting for containers to start or be ready - Indefinite one shot startup strategy example","url":"/sourcey/features/startup-and-waits.html#indefinite-one-shot-startup-strategy-example","tab":"Java Guide","category":"Sections"},{"title":"Minimum duration startup strategy example","content":"Waiting for containers to start or be ready - Minimum duration startup strategy example","url":"/sourcey/features/startup-and-waits.html#minimum-duration-startup-strategy-example","tab":"Java Guide","category":"Sections"},{"title":"Other startup strategies","content":"Waiting for containers to start or be ready - Other startup strategies","url":"/sourcey/features/startup-and-waits.html#other-startup-strategies","tab":"Java Guide","category":"Sections"},{"title":"Depending on another container","content":"Waiting for containers to start or be ready - Depending on another container","url":"/sourcey/features/startup-and-waits.html#depending-on-another-container","tab":"Java Guide","category":"Sections"},{"title":"Accessing container logs","content":"It is possible to capture container output using:","url":"/sourcey/features/container-logs.html","tab":"Java Guide","category":"Pages"},{"title":"Reading all logs (from startup time to present)","content":"Accessing container logs - Reading all logs (from startup time to present)","url":"/sourcey/features/container-logs.html#reading-all-logs-from-startup-time-to-present","tab":"Java Guide","category":"Sections"},{"title":"Streaming logs","content":"Accessing container logs - Streaming logs","url":"/sourcey/features/container-logs.html#streaming-logs","tab":"Java Guide","category":"Sections"},{"title":"Streaming container output to an SLF4J logger","content":"Accessing container logs - Streaming container output to an SLF4J logger","url":"/sourcey/features/container-logs.html#streaming-container-output-to-an-slf4j-logger","tab":"Java Guide","category":"Sections"},{"title":"Capturing container output as a String","content":"Accessing container logs - Capturing container output as a String","url":"/sourcey/features/container-logs.html#capturing-container-output-as-a-string","tab":"Java Guide","category":"Sections"},{"title":"Waiting for container output to contain expected content","content":"Accessing container logs - Waiting for container output to contain expected content","url":"/sourcey/features/container-logs.html#waiting-for-container-output-to-contain-expected-content","tab":"Java Guide","category":"Sections"},{"title":"Creating images on-the-fly","content":"In situations where there is no pre-existing Docker image, Testcontainers can create a new temporary image on-the-fly from a Dockerfile. For example, when the component under test is the Docker image itself, or when an existing base image needs to be customized for specific test(s).","url":"/sourcey/features/creating-images.html","tab":"Java Guide","category":"Pages"},{"title":"Overview","content":"Creating images on-the-fly - Overview","url":"/sourcey/features/creating-images.html#overview","tab":"Java Guide","category":"Sections"},{"title":"Dockerfile from String, file or classpath resource","content":"Creating images on-the-fly - Dockerfile from String, file or classpath resource","url":"/sourcey/features/creating-images.html#dockerfile-from-string-file-or-classpath-resource","tab":"Java Guide","category":"Sections"},{"title":"Dockerfile DSL","content":"Creating images on-the-fly - Dockerfile DSL","url":"/sourcey/features/creating-images.html#dockerfile-dsl","tab":"Java Guide","category":"Sections"},{"title":"Automatic deletion","content":"Creating images on-the-fly - Automatic deletion","url":"/sourcey/features/creating-images.html#automatic-deletion","tab":"Java Guide","category":"Sections"},{"title":"Alternative Dockerfiles","content":"Creating images on-the-fly - Alternative Dockerfiles","url":"/sourcey/features/creating-images.html#alternative-dockerfiles","tab":"Java Guide","category":"Sections"},{"title":"Build Args","content":"Creating images on-the-fly - Build Args","url":"/sourcey/features/creating-images.html#build-args","tab":"Java Guide","category":"Sections"},{"title":"Custom configuration","content":"You can override some default properties if your environment requires that.","url":"/sourcey/features/configuration.html","tab":"Java Guide","category":"Pages"},{"title":"Configuration locations","content":"Custom configuration - Configuration locations","url":"/sourcey/features/configuration.html#configuration-locations","tab":"Java Guide","category":"Sections"},{"title":"Disabling the startup checks","content":"Custom configuration - Disabling the startup checks","url":"/sourcey/features/configuration.html#disabling-the-startup-checks","tab":"Java Guide","category":"Sections"},{"title":"Customizing images","content":"Custom configuration - Customizing images","url":"/sourcey/features/configuration.html#customizing-images","tab":"Java Guide","category":"Sections"},{"title":"Customizing Ryuk resource reaper","content":"Custom configuration - Customizing Ryuk resource reaper","url":"/sourcey/features/configuration.html#customizing-ryuk-resource-reaper","tab":"Java Guide","category":"Sections"},{"title":"Disabling Ryuk","content":"Custom configuration - Disabling Ryuk","url":"/sourcey/features/configuration.html#disabling-ryuk","tab":"Java Guide","category":"Sections"},{"title":"Customizing image pull behaviour","content":"Custom configuration - Customizing image pull behaviour","url":"/sourcey/features/configuration.html#customizing-image-pull-behaviour","tab":"Java Guide","category":"Sections"},{"title":"Customizing client ping behaviour","content":"Custom configuration - Customizing client ping behaviour","url":"/sourcey/features/configuration.html#customizing-client-ping-behaviour","tab":"Java Guide","category":"Sections"},{"title":"Customizing Docker host detection","content":"Custom configuration - Customizing Docker host detection","url":"/sourcey/features/configuration.html#customizing-docker-host-detection","tab":"Java Guide","category":"Sections"},{"title":"Image name substitution","content":"Testcontainers supports automatic substitution of Docker image names.","url":"/sourcey/features/image-name-substitution.html","tab":"Java Guide","category":"Pages"},{"title":"Manual substitution","content":"Image name substitution - Manual substitution","url":"/sourcey/features/image-name-substitution.html#manual-substitution","tab":"Java Guide","category":"Sections"},{"title":"Automatically modifying Docker Hub image names","content":"Image name substitution - Automatically modifying Docker Hub image names","url":"/sourcey/features/image-name-substitution.html#automatically-modifying-docker-hub-image-names","tab":"Java Guide","category":"Sections"},{"title":"Developing a custom function for transforming image names on the fly","content":"Image name substitution - Developing a custom function for transforming image names on the fly","url":"/sourcey/features/image-name-substitution.html#developing-a-custom-function-for-transforming-image-names-on-the-fly","tab":"Java Guide","category":"Sections"},{"title":"Overriding image names individually in configuration","content":"Image name substitution - Overriding image names individually in configuration","url":"/sourcey/features/image-name-substitution.html#overriding-image-names-individually-in-configuration","tab":"Java Guide","category":"Sections"},{"title":"Advanced options","content":"To add a custom label to the container, use `withLabel`:","url":"/sourcey/features/advanced-options.html","tab":"Java Guide","category":"Pages"},{"title":"Container labels","content":"Advanced options - Container labels","url":"/sourcey/features/advanced-options.html#container-labels","tab":"Java Guide","category":"Sections"},{"title":"Image Pull Policy","content":"Advanced options - Image Pull Policy","url":"/sourcey/features/advanced-options.html#image-pull-policy","tab":"Java Guide","category":"Sections"},{"title":"Customizing the container","content":"Advanced options - Customizing the container","url":"/sourcey/features/advanced-options.html#customizing-the-container","tab":"Java Guide","category":"Sections"},{"title":"Using docker-java","content":"Advanced options - Using docker-java","url":"/sourcey/features/advanced-options.html#using-docker-java","tab":"Java Guide","category":"Sections"},{"title":"Using CreateContainerCmdModifier","content":"Advanced options - Using CreateContainerCmdModifier","url":"/sourcey/features/advanced-options.html#using-createcontainercmdmodifier","tab":"Java Guide","category":"Sections"},{"title":"Parallel Container Startup","content":"Advanced options - Parallel Container Startup","url":"/sourcey/features/advanced-options.html#parallel-container-startup","tab":"Java Guide","category":"Sections"},{"title":"Reusable Containers (Experimental)","content":"The *Reusable* feature keeps the containers running and next executions with the same container configuration will reuse it. To use it, start the container manually by calling `start()` method, do not call `stop()` method directly or indirectly via `try-with-resources` or `JUnit integration`, and enable it manually through an opt-in mechanism per environment. To reuse a container, the container configuration **must be the same**.","url":"/sourcey/features/reuse.html","tab":"Java Guide","category":"Pages"},{"title":"How to use it","content":"Reusable Containers (Experimental) - How to use it","url":"/sourcey/features/reuse.html#how-to-use-it","tab":"Java Guide","category":"Sections"},{"title":"Reusable Container with Testcontainers JDBC URL","content":"Reusable Containers (Experimental) - Reusable Container with Testcontainers JDBC URL","url":"/sourcey/features/reuse.html#reusable-container-with-testcontainers-jdbc-url","tab":"Java Guide","category":"Sections"},{"title":"Database containers","content":"You might want to use Testcontainers' database support:","url":"/sourcey/modules/databases/","tab":"Java Guide","category":"Pages"},{"title":"Overview","content":"Database containers - Overview","url":"/sourcey/modules/databases/#overview","tab":"Java Guide","category":"Sections"},{"title":"JDBC support","content":"You can obtain a temporary database in one of two ways:","url":"/sourcey/modules/databases/jdbc.html","tab":"Java Guide","category":"Pages"},{"title":"Database containers launched via JDBC URL scheme","content":"JDBC support - Database containers launched via JDBC URL scheme","url":"/sourcey/modules/databases/jdbc.html#database-containers-launched-via-jdbc-url-scheme","tab":"Java Guide","category":"Sections"},{"title":"JDBC URL examples","content":"JDBC support - JDBC URL examples","url":"/sourcey/modules/databases/jdbc.html#jdbc-url-examples","tab":"Java Guide","category":"Sections"},{"title":"Using a classpath init script","content":"JDBC support - Using a classpath init script","url":"/sourcey/modules/databases/jdbc.html#using-a-classpath-init-script","tab":"Java Guide","category":"Sections"},{"title":"Using an init script from a file","content":"JDBC support - Using an init script from a file","url":"/sourcey/modules/databases/jdbc.html#using-an-init-script-from-a-file","tab":"Java Guide","category":"Sections"},{"title":"Using an init function","content":"JDBC support - Using an init function","url":"/sourcey/modules/databases/jdbc.html#using-an-init-function","tab":"Java Guide","category":"Sections"},{"title":"Running container in daemon mode","content":"JDBC support - Running container in daemon mode","url":"/sourcey/modules/databases/jdbc.html#running-container-in-daemon-mode","tab":"Java Guide","category":"Sections"},{"title":"Running container with tmpfs options","content":"JDBC support - Running container with tmpfs options","url":"/sourcey/modules/databases/jdbc.html#running-container-with-tmpfs-options","tab":"Java Guide","category":"Sections"},{"title":"Database container objects","content":"JDBC support - Database container objects","url":"/sourcey/modules/databases/jdbc.html#database-container-objects","tab":"Java Guide","category":"Sections"},{"title":"Postgres Module","content":"Testcontainers module for PostgresSQL","url":"/sourcey/modules/databases/postgres.html","tab":"Java Guide","category":"Pages"},{"title":"Usage example","content":"Postgres Module - Usage example","url":"/sourcey/modules/databases/postgres.html#usage-example","tab":"Java Guide","category":"Sections"},{"title":"Testcontainers JDBC URL","content":"Postgres Module - Testcontainers JDBC URL","url":"/sourcey/modules/databases/postgres.html#testcontainers-jdbc-url","tab":"Java Guide","category":"Sections"},{"title":"Compatible images","content":"Postgres Module - Compatible images","url":"/sourcey/modules/databases/postgres.html#compatible-images","tab":"Java Guide","category":"Sections"},{"title":"Adding this module to your project dependencies","content":"Postgres Module - Adding this module to your project dependencies","url":"/sourcey/modules/databases/postgres.html#adding-this-module-to-your-project-dependencies","tab":"Java Guide","category":"Sections"},{"title":"MySQL Module","content":"Testcontainers module for MySQL","url":"/sourcey/modules/databases/mysql.html","tab":"Java Guide","category":"Pages"},{"title":"Usage example","content":"MySQL Module - Usage example","url":"/sourcey/modules/databases/mysql.html#usage-example","tab":"Java Guide","category":"Sections"},{"title":"Testcontainers JDBC URL","content":"MySQL Module - Testcontainers JDBC URL","url":"/sourcey/modules/databases/mysql.html#testcontainers-jdbc-url","tab":"Java Guide","category":"Sections"},{"title":"Overriding MySQL my.cnf settings","content":"MySQL Module - Overriding MySQL my.cnf settings","url":"/sourcey/modules/databases/mysql.html#overriding-mysql-my-cnf-settings","tab":"Java Guide","category":"Sections"},{"title":"MySQL root user password","content":"MySQL Module - MySQL root user password","url":"/sourcey/modules/databases/mysql.html#mysql-root-user-password","tab":"Java Guide","category":"Sections"},{"title":"Adding this module to your project dependencies","content":"MySQL Module - Adding this module to your project dependencies","url":"/sourcey/modules/databases/mysql.html#adding-this-module-to-your-project-dependencies","tab":"Java Guide","category":"Sections"},{"title":"MongoDB Module","content":"The MongoDB module provides two Testcontainers for MongoDB unit testing:","url":"/sourcey/modules/databases/mongodb.html","tab":"Java Guide","category":"Pages"},{"title":"MongoDBContainer","content":"MongoDB Module - MongoDBContainer","url":"/sourcey/modules/databases/mongodb.html#mongodbcontainer","tab":"Java Guide","category":"Sections"},{"title":"Usage example","content":"MongoDB Module - Usage example","url":"/sourcey/modules/databases/mongodb.html#usage-example","tab":"Java Guide","category":"Sections"},{"title":"MongoDBAtlasLocalContainer","content":"MongoDB Module - MongoDBAtlasLocalContainer","url":"/sourcey/modules/databases/mongodb.html#mongodbatlaslocalcontainer","tab":"Java Guide","category":"Sections"},{"title":"Usage example","content":"MongoDB Module - Usage example","url":"/sourcey/modules/databases/mongodb.html#usage-example","tab":"Java Guide","category":"Sections"},{"title":"References","content":"MongoDB Module - References","url":"/sourcey/modules/databases/mongodb.html#references","tab":"Java Guide","category":"Sections"},{"title":"Adding this module to your project dependencies","content":"MongoDB Module - Adding this module to your project dependencies","url":"/sourcey/modules/databases/mongodb.html#adding-this-module-to-your-project-dependencies","tab":"Java Guide","category":"Sections"},{"title":"Kafka Module","content":"Testcontainers can be used to automatically instantiate and manage Apache Kafka containers.","url":"/sourcey/modules/kafka.html","tab":"Java Guide","category":"Pages"},{"title":"Benefits","content":"Kafka Module - Benefits","url":"/sourcey/modules/kafka.html#benefits","tab":"Java Guide","category":"Sections"},{"title":"Example","content":"Kafka Module - Example","url":"/sourcey/modules/kafka.html#example","tab":"Java Guide","category":"Sections"},{"title":"Using org.testcontainers.kafka.KafkaContainer","content":"Kafka Module - Using org.testcontainers.kafka.KafkaContainer","url":"/sourcey/modules/kafka.html#using-org-testcontainers-kafka-kafkacontainer","tab":"Java Guide","category":"Sections"},{"title":"Using org.testcontainers.kafka.ConfluentKafkaContainer","content":"Kafka Module - Using org.testcontainers.kafka.ConfluentKafkaContainer","url":"/sourcey/modules/kafka.html#using-org-testcontainers-kafka-confluentkafkacontainer","tab":"Java Guide","category":"Sections"},{"title":"Options","content":"Kafka Module - Options","url":"/sourcey/modules/kafka.html#options","tab":"Java Guide","category":"Sections"},{"title":"Using Kraft mode","content":"Kafka Module - Using Kraft mode","url":"/sourcey/modules/kafka.html#using-kraft-mode","tab":"Java Guide","category":"Sections"},{"title":"Register listeners","content":"Kafka Module - Register listeners","url":"/sourcey/modules/kafka.html#register-listeners","tab":"Java Guide","category":"Sections"},{"title":"Adding this module to your project dependencies","content":"Kafka Module - Adding this module to your project dependencies","url":"/sourcey/modules/kafka.html#adding-this-module-to-your-project-dependencies","tab":"Java Guide","category":"Sections"},{"title":"LocalStack Module","content":"Testcontainers module for LocalStack, 'a fully functional local AWS cloud stack', to develop and test your cloud and serverless apps without actually using the cloud.","url":"/sourcey/modules/localstack.html","tab":"Java Guide","category":"Pages"},{"title":"Usage example","content":"LocalStack Module - Usage example","url":"/sourcey/modules/localstack.html#usage-example","tab":"Java Guide","category":"Sections"},{"title":"Creating a client using AWS SDK","content":"LocalStack Module - Creating a client using AWS SDK","url":"/sourcey/modules/localstack.html#creating-a-client-using-aws-sdk","tab":"Java Guide","category":"Sections"},{"title":"Adding this module to your project dependencies","content":"LocalStack Module - Adding this module to your project dependencies","url":"/sourcey/modules/localstack.html#adding-this-module-to-your-project-dependencies","tab":"Java Guide","category":"Sections"},{"title":"Toxiproxy Module","content":"Testcontainers module for Shopify's Toxiproxy. This TCP proxy can be used to simulate network failure conditions.","url":"/sourcey/modules/toxiproxy.html","tab":"Java Guide","category":"Pages"},{"title":"Usage example","content":"Toxiproxy Module - Usage example","url":"/sourcey/modules/toxiproxy.html#usage-example","tab":"Java Guide","category":"Sections"},{"title":"Adding this module to your project dependencies","content":"Toxiproxy Module - Adding this module to your project dependencies","url":"/sourcey/modules/toxiproxy.html#adding-this-module-to-your-project-dependencies","tab":"Java Guide","category":"Sections"},{"title":"Acknowledgements","content":"Toxiproxy Module - Acknowledgements","url":"/sourcey/modules/toxiproxy.html#acknowledgements","tab":"Java Guide","category":"Sections"},{"title":"Jupiter / JUnit 5","content":"This module provides an API that is based on the JUnit Jupiter extension model.","url":"/sourcey/test-framework-integration/junit-5.html","tab":"Java Guide","category":"Pages"},{"title":"Extension","content":"Jupiter / JUnit 5 - Extension","url":"/sourcey/test-framework-integration/junit-5.html#extension","tab":"Java Guide","category":"Sections"},{"title":"Examples","content":"Jupiter / JUnit 5 - Examples","url":"/sourcey/test-framework-integration/junit-5.html#examples","tab":"Java Guide","category":"Sections"},{"title":"Restarted containers","content":"Jupiter / JUnit 5 - Restarted containers","url":"/sourcey/test-framework-integration/junit-5.html#restarted-containers","tab":"Java Guide","category":"Sections"},{"title":"Shared containers","content":"Jupiter / JUnit 5 - Shared containers","url":"/sourcey/test-framework-integration/junit-5.html#shared-containers","tab":"Java Guide","category":"Sections"},{"title":"Singleton containers","content":"Jupiter / JUnit 5 - Singleton containers","url":"/sourcey/test-framework-integration/junit-5.html#singleton-containers","tab":"Java Guide","category":"Sections"},{"title":"Limitations","content":"Jupiter / JUnit 5 - Limitations","url":"/sourcey/test-framework-integration/junit-5.html#limitations","tab":"Java Guide","category":"Sections"},{"title":"Adding Testcontainers JUnit 5 support to your project dependencies","content":"Jupiter / JUnit 5 - Adding Testcontainers JUnit 5 support to your project dependencies","url":"/sourcey/test-framework-integration/junit-5.html#adding-testcontainers-junit-5-support-to-your-project-dependencies","tab":"Java Guide","category":"Sections"}] \ No newline at end of file diff --git a/docs/sourcey/sitemap.xml b/docs/sourcey/sitemap.xml new file mode 100644 index 00000000000..c006c8f47f9 --- /dev/null +++ b/docs/sourcey/sitemap.xml @@ -0,0 +1,29 @@ + + + + https://java.testcontainers.org/sourcey/ + https://java.testcontainers.org/sourcey/examples.html + https://java.testcontainers.org/sourcey/quickstart/junit-4-quickstart.html + https://java.testcontainers.org/sourcey/quickstart/junit-5-quickstart.html + https://java.testcontainers.org/sourcey/quickstart/spock-quickstart.html + https://java.testcontainers.org/sourcey/features/creating-container.html + https://java.testcontainers.org/sourcey/features/networking.html + https://java.testcontainers.org/sourcey/features/commands.html + https://java.testcontainers.org/sourcey/features/files.html + https://java.testcontainers.org/sourcey/features/startup-and-waits.html + https://java.testcontainers.org/sourcey/features/container-logs.html + https://java.testcontainers.org/sourcey/features/creating-images.html + https://java.testcontainers.org/sourcey/features/configuration.html + https://java.testcontainers.org/sourcey/features/image-name-substitution.html + https://java.testcontainers.org/sourcey/features/advanced-options.html + https://java.testcontainers.org/sourcey/features/reuse.html + https://java.testcontainers.org/sourcey/modules/databases/ + https://java.testcontainers.org/sourcey/modules/databases/jdbc.html + https://java.testcontainers.org/sourcey/modules/databases/postgres.html + https://java.testcontainers.org/sourcey/modules/databases/mysql.html + https://java.testcontainers.org/sourcey/modules/databases/mongodb.html + https://java.testcontainers.org/sourcey/modules/kafka.html + https://java.testcontainers.org/sourcey/modules/localstack.html + https://java.testcontainers.org/sourcey/modules/toxiproxy.html + https://java.testcontainers.org/sourcey/test-framework-integration/junit-5.html + \ No newline at end of file diff --git a/docs/sourcey/sourcey.css b/docs/sourcey/sourcey.css new file mode 100644 index 00000000000..d275553db22 --- /dev/null +++ b/docs/sourcey/sourcey.css @@ -0,0 +1,2210 @@ +/*! tailwindcss v4.3.2 | MIT License | https://tailwindcss.com */ +@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-translate-x:0;--tw-translate-y:0;--tw-translate-z:0;--tw-rotate-x:initial;--tw-rotate-y:initial;--tw-rotate-z:initial;--tw-skew-x:initial;--tw-skew-y:initial;--tw-space-y-reverse:0;--tw-space-x-reverse:0;--tw-border-style:solid;--tw-gradient-position:initial;--tw-gradient-from:#0000;--tw-gradient-via:#0000;--tw-gradient-to:#0000;--tw-gradient-stops:initial;--tw-gradient-via-stops:initial;--tw-gradient-from-position:0%;--tw-gradient-via-position:50%;--tw-gradient-to-position:100%;--tw-leading:initial;--tw-font-weight:initial;--tw-tracking:initial;--tw-ordinal:initial;--tw-slashed-zero:initial;--tw-numeric-figure:initial;--tw-numeric-spacing:initial;--tw-numeric-fraction:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-outline-style:solid;--tw-backdrop-blur:initial;--tw-backdrop-brightness:initial;--tw-backdrop-contrast:initial;--tw-backdrop-grayscale:initial;--tw-backdrop-hue-rotate:initial;--tw-backdrop-invert:initial;--tw-backdrop-opacity:initial;--tw-backdrop-saturate:initial;--tw-backdrop-sepia:initial;--tw-blur:initial;--tw-brightness:initial;--tw-contrast:initial;--tw-grayscale:initial;--tw-hue-rotate:initial;--tw-invert:initial;--tw-opacity:initial;--tw-saturate:initial;--tw-sepia:initial;--tw-drop-shadow:initial;--tw-drop-shadow-color:initial;--tw-drop-shadow-alpha:100%;--tw-drop-shadow-size:initial}}}@layer theme{:root,:host{--font-sans:"Inter", ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;--font-mono:ui-monospace, "SF Mono", "Cascadia Code", Consolas, "Liberation Mono", Menlo, monospace;--color-red-100:oklch(93.6% .032 17.717);--color-red-300:oklch(80.8% .114 19.571);--color-red-400:oklch(70.4% .191 22.216);--color-red-600:oklch(57.7% .245 27.325);--color-red-800:oklch(44.4% .177 26.899);--color-orange-100:oklch(95.4% .038 75.164);--color-orange-300:oklch(83.7% .128 66.29);--color-orange-400:oklch(75% .183 55.934);--color-orange-900:oklch(40.8% .123 38.172);--color-amber-50:oklch(98.7% .022 95.277);--color-amber-100:oklch(96.2% .059 95.617);--color-amber-200:oklch(92.4% .12 95.746);--color-amber-300:oklch(87.9% .169 91.605);--color-amber-400:oklch(82.8% .189 84.429);--color-amber-600:oklch(66.6% .179 58.318);--color-amber-700:oklch(55.5% .163 48.998);--color-amber-800:oklch(47.3% .137 46.201);--color-amber-900:oklch(41.4% .112 45.904);--color-yellow-300:oklch(90.5% .182 98.111);--color-yellow-400:oklch(85.2% .199 91.936);--color-green-100:oklch(96.2% .044 156.743);--color-green-300:oklch(87.1% .15 154.449);--color-green-400:oklch(79.2% .209 151.711);--color-green-500:oklch(72.3% .219 149.579);--color-green-600:oklch(62.7% .194 149.214);--color-green-700:oklch(52.7% .154 150.069);--color-green-800:oklch(44.8% .119 151.328);--color-emerald-50:oklch(97.9% .021 166.113);--color-emerald-200:oklch(90.5% .093 164.15);--color-emerald-400:oklch(76.5% .177 163.223);--color-emerald-500:oklch(69.6% .17 162.48);--color-emerald-900:oklch(37.8% .077 168.94);--color-blue-100:oklch(93.2% .032 255.585);--color-blue-300:oklch(80.9% .105 251.813);--color-blue-400:oklch(70.7% .165 254.624);--color-blue-500:oklch(62.3% .214 259.815);--color-blue-600:oklch(54.6% .245 262.881);--color-blue-700:oklch(48.8% .243 264.376);--color-blue-800:oklch(42.4% .199 265.638);--color-indigo-300:oklch(78.5% .115 274.713);--color-indigo-600:oklch(51.1% .262 276.966);--color-purple-400:oklch(71.4% .203 305.504);--color-purple-500:oklch(62.7% .265 303.9);--color-purple-700:oklch(49.6% .265 301.924);--color-rose-50:oklch(96.9% .015 12.422);--color-rose-100:oklch(94.1% .03 12.58);--color-rose-200:oklch(89.2% .058 10.001);--color-rose-300:oklch(81% .117 11.638);--color-rose-600:oklch(58.6% .253 17.585);--color-rose-800:oklch(45.5% .188 13.697);--color-rose-900:oklch(41% .159 10.272);--color-gray-50:245 245 250;--color-gray-100:241 241 245;--color-gray-200:225 225 229;--color-gray-300:209 209 213;--color-gray-400:161 161 165;--color-gray-500:115 115 119;--color-gray-600:83 83 87;--color-gray-700:65 65 69;--color-gray-800:40 40 44;--color-gray-900:25 25 30;--color-gray-950:13 13 17;--color-stone-50:250 250 249;--color-stone-100:245 245 244;--color-stone-200:231 229 228;--color-stone-400:168 162 158;--color-stone-500:120 113 108;--color-stone-600:87 83 78;--color-stone-700:68 64 60;--color-stone-900:oklch(21.6% .006 56.043);--color-stone-950:12 10 9;--color-white:#fff;--spacing:.25rem;--container-2xl:42rem;--container-3xl:48rem;--text-xs:.75rem;--text-xs--line-height:calc(1 / .75);--text-sm:.875rem;--text-sm--line-height:calc(1.25 / .875);--text-lg:1.125rem;--text-lg--line-height:calc(1.75 / 1.125);--text-xl:1.25rem;--text-xl--line-height:calc(1.75 / 1.25);--text-2xl:1.5rem;--text-2xl--line-height:calc(2 / 1.5);--text-3xl:1.875rem;--text-3xl--line-height:calc(2.25 / 1.875);--font-weight-normal:400;--font-weight-medium:500;--font-weight-semibold:600;--font-weight-bold:700;--tracking-tight:-.025em;--leading-tight:1.25;--radius-md:.375rem;--radius-lg:.5rem;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4, 0, .2, 1);--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono);--radius:.75rem;--sidebar-width:18rem;--header-height:7rem;--toc-width:19rem;--toc-inner-width:16.5rem;--content-padding:2.5rem;--content-max-width:44rem;--color-primary:99 102 241;--color-primary-light:129 140 248;--color-primary-dark:79 70 229;--color-primary-ink:79 70 229;--color-background-light:255 255 255;--color-background-dark:11 12 16;--color-code-block-light:255 255 255;--color-code-block-dark:11 12 14;--color-success:34 197 94;--color-overlay:0 0 0;--color-border-dark-subtle:255 255 255;--color-surface-dark-tint:255 255 255;--method-get:#16a34a;--method-post:#2563eb;--method-put:#d97706;--method-delete:#dc2626;--method-patch:#9333ea;--method-tool:#9333ea;--method-resource:#16a34a;--method-prompt:#2563eb}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;tab-size:4;line-height:1.5;font-family:var(--default-font-family,ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring{outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab, red, red)){::placeholder{color:color-mix(in oklab, currentcolor 50%, transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){appearance:button}::file-selector-button{appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}}@layer components;@layer utilities{.pointer-events-auto{pointer-events:auto}.pointer-events-none{pointer-events:none}.collapse{visibility:collapse}.visible{visibility:visible}.absolute{position:absolute}.fixed{position:fixed}.relative{position:relative}.static{position:static}.sticky{position:sticky}.inset-0{inset:0}.top-0{top:0}.top-3{top:calc(var(--spacing) * 3)}.top-\[2\.75rem\]{top:2.75rem}.top-full{top:100%}.right-0{right:0}.right-4{right:calc(var(--spacing) * 4)}.right-auto{right:auto}.bottom-0{bottom:0}.left-0{left:0}.left-1\/2{left:50%}.-z-10{z-index:calc(10 * -1)}.z-10{z-index:10}.z-20{z-index:20}.z-30{z-index:30}.z-\[21\]{z-index:21}.container{width:100%}@media (width>=40rem){.container{max-width:40rem}}@media (width>=48rem){.container{max-width:48rem}}@media (width>=64rem){.container{max-width:64rem}}@media (width>=80rem){.container{max-width:80rem}}@media (width>=96rem){.container{max-width:96rem}}.mx-4{margin-inline:calc(var(--spacing) * 4)}.mx-auto{margin-inline:auto}.my-1{margin-block:var(--spacing)}.prose{color:var(--tw-prose-body);max-width:65ch}.prose :where(p):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:1.25em;margin-bottom:1.25em}.prose :where([class~=lead]):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-lead);margin-top:1.2em;margin-bottom:1.2em;font-size:1.25em;line-height:1.6}.prose :where(a):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-links);font-weight:500;text-decoration:underline}.prose :where(strong):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-bold);font-weight:600}.prose :where(a strong):not(:where([class~=not-prose],[class~=not-prose] *)),.prose :where(blockquote strong):not(:where([class~=not-prose],[class~=not-prose] *)),.prose :where(thead th strong):not(:where([class~=not-prose],[class~=not-prose] *)){color:inherit}.prose :where(ol):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:1.25em;margin-bottom:1.25em;padding-inline-start:1.625em;list-style-type:decimal}.prose :where(ol[type=A]):not(:where([class~=not-prose],[class~=not-prose] *)){list-style-type:upper-alpha}.prose :where(ol[type=a]):not(:where([class~=not-prose],[class~=not-prose] *)){list-style-type:lower-alpha}.prose :where(ol[type=A s]):not(:where([class~=not-prose],[class~=not-prose] *)){list-style-type:upper-alpha}.prose :where(ol[type=a s]):not(:where([class~=not-prose],[class~=not-prose] *)){list-style-type:lower-alpha}.prose :where(ol[type=I]):not(:where([class~=not-prose],[class~=not-prose] *)){list-style-type:upper-roman}.prose :where(ol[type=i]):not(:where([class~=not-prose],[class~=not-prose] *)){list-style-type:lower-roman}.prose :where(ol[type=I s]):not(:where([class~=not-prose],[class~=not-prose] *)){list-style-type:upper-roman}.prose :where(ol[type=i s]):not(:where([class~=not-prose],[class~=not-prose] *)){list-style-type:lower-roman}.prose :where(ol[type="1"]):not(:where([class~=not-prose],[class~=not-prose] *)){list-style-type:decimal}.prose :where(ul):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:1.25em;margin-bottom:1.25em;padding-inline-start:1.625em;list-style-type:disc}.prose :where(ol>li):not(:where([class~=not-prose],[class~=not-prose] *))::marker{color:var(--tw-prose-counters);font-weight:400}.prose :where(ul>li):not(:where([class~=not-prose],[class~=not-prose] *))::marker{color:var(--tw-prose-bullets)}.prose :where(dt):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-headings);margin-top:1.25em;font-weight:600}.prose :where(hr):not(:where([class~=not-prose],[class~=not-prose] *)){border-color:var(--tw-prose-hr);border-top-width:1px;margin-top:3em;margin-bottom:3em}.prose :where(blockquote):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-quotes);border-inline-start-width:.25rem;border-inline-start-color:var(--tw-prose-quote-borders);quotes:"“""”""‘""’";margin-top:1.6em;margin-bottom:1.6em;padding-inline-start:1em;font-style:italic;font-weight:500}.prose :where(blockquote p:first-of-type):not(:where([class~=not-prose],[class~=not-prose] *)):before{content:open-quote}.prose :where(blockquote p:last-of-type):not(:where([class~=not-prose],[class~=not-prose] *)):after{content:close-quote}.prose :where(h1):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-headings);margin-top:0;margin-bottom:.888889em;font-size:2.25em;font-weight:800;line-height:1.11111}.prose :where(h1 strong):not(:where([class~=not-prose],[class~=not-prose] *)){color:inherit;font-weight:900}.prose :where(h2):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-headings);margin-top:2em;margin-bottom:1em;font-size:1.5em;font-weight:700;line-height:1.33333}.prose :where(h2 strong):not(:where([class~=not-prose],[class~=not-prose] *)){color:inherit;font-weight:800}.prose :where(h3):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-headings);margin-top:1.6em;margin-bottom:.6em;font-size:1.25em;font-weight:600;line-height:1.6}.prose :where(h3 strong):not(:where([class~=not-prose],[class~=not-prose] *)){color:inherit;font-weight:700}.prose :where(h4):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-headings);margin-top:1.5em;margin-bottom:.5em;font-weight:600;line-height:1.5}.prose :where(h4 strong):not(:where([class~=not-prose],[class~=not-prose] *)){color:inherit;font-weight:700}.prose :where(img):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:2em;margin-bottom:2em}.prose :where(picture):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:2em;margin-bottom:2em;display:block}.prose :where(video):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:2em;margin-bottom:2em}.prose :where(kbd):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-kbd);box-shadow:0 0 0 1px var(--tw-prose-kbd-shadows), 0 3px 0 var(--tw-prose-kbd-shadows);padding-top:.1875em;padding-inline-end:.375em;padding-bottom:.1875em;border-radius:.3125rem;padding-inline-start:.375em;font-family:inherit;font-size:.875em;font-weight:500}.prose :where(code):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-code);font-size:.875em;font-weight:600}.prose :where(code):not(:where([class~=not-prose],[class~=not-prose] *)):before,.prose :where(code):not(:where([class~=not-prose],[class~=not-prose] *)):after{content:"`"}.prose :where(a code):not(:where([class~=not-prose],[class~=not-prose] *)),.prose :where(h1 code):not(:where([class~=not-prose],[class~=not-prose] *)){color:inherit}.prose :where(h2 code):not(:where([class~=not-prose],[class~=not-prose] *)){color:inherit;font-size:.875em}.prose :where(h3 code):not(:where([class~=not-prose],[class~=not-prose] *)){color:inherit;font-size:.9em}.prose :where(h4 code):not(:where([class~=not-prose],[class~=not-prose] *)),.prose :where(blockquote code):not(:where([class~=not-prose],[class~=not-prose] *)),.prose :where(thead th code):not(:where([class~=not-prose],[class~=not-prose] *)){color:inherit}.prose :where(pre):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-pre-code);background-color:var(--tw-prose-pre-bg);padding-top:.857143em;padding-inline-end:1.14286em;padding-bottom:.857143em;border-radius:.375rem;margin-top:1.71429em;margin-bottom:1.71429em;padding-inline-start:1.14286em;font-size:.875em;font-weight:400;line-height:1.71429;overflow-x:auto}.prose :where(pre code):not(:where([class~=not-prose],[class~=not-prose] *)){font-weight:inherit;color:inherit;font-size:inherit;font-family:inherit;line-height:inherit;background-color:#0000;border-width:0;border-radius:0;padding:0}.prose :where(pre code):not(:where([class~=not-prose],[class~=not-prose] *)):before,.prose :where(pre code):not(:where([class~=not-prose],[class~=not-prose] *)):after{content:none}.prose :where(table):not(:where([class~=not-prose],[class~=not-prose] *)){table-layout:auto;width:100%;margin-top:2em;margin-bottom:2em;font-size:.875em;line-height:1.71429}.prose :where(thead):not(:where([class~=not-prose],[class~=not-prose] *)){border-bottom-width:1px;border-bottom-color:var(--tw-prose-th-borders)}.prose :where(thead th):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-headings);vertical-align:bottom;padding-inline-end:.571429em;padding-bottom:.571429em;padding-inline-start:.571429em;font-weight:600}.prose :where(tbody tr):not(:where([class~=not-prose],[class~=not-prose] *)){border-bottom-width:1px;border-bottom-color:var(--tw-prose-td-borders)}.prose :where(tbody tr:last-child):not(:where([class~=not-prose],[class~=not-prose] *)){border-bottom-width:0}.prose :where(tbody td):not(:where([class~=not-prose],[class~=not-prose] *)){vertical-align:baseline}.prose :where(tfoot):not(:where([class~=not-prose],[class~=not-prose] *)){border-top-width:1px;border-top-color:var(--tw-prose-th-borders)}.prose :where(tfoot td):not(:where([class~=not-prose],[class~=not-prose] *)){vertical-align:top}.prose :where(th,td):not(:where([class~=not-prose],[class~=not-prose] *)){text-align:start}.prose :where(figure>*):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:0;margin-bottom:0}.prose :where(figcaption):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-captions);margin-top:.857143em;font-size:.875em;line-height:1.42857}.prose{--tw-prose-body:oklch(37.3% .034 259.733);--tw-prose-headings:oklch(21% .034 264.665);--tw-prose-lead:oklch(44.6% .03 256.802);--tw-prose-links:oklch(21% .034 264.665);--tw-prose-bold:oklch(21% .034 264.665);--tw-prose-counters:oklch(55.1% .027 264.364);--tw-prose-bullets:oklch(87.2% .01 258.338);--tw-prose-hr:oklch(92.8% .006 264.531);--tw-prose-quotes:oklch(21% .034 264.665);--tw-prose-quote-borders:oklch(92.8% .006 264.531);--tw-prose-captions:oklch(55.1% .027 264.364);--tw-prose-kbd:oklch(21% .034 264.665);--tw-prose-kbd-shadows:oklab(21% -.00316127 -.0338527/.1);--tw-prose-code:oklch(21% .034 264.665);--tw-prose-pre-code:oklch(92.8% .006 264.531);--tw-prose-pre-bg:oklch(27.8% .033 256.848);--tw-prose-th-borders:oklch(87.2% .01 258.338);--tw-prose-td-borders:oklch(92.8% .006 264.531);--tw-prose-invert-body:oklch(87.2% .01 258.338);--tw-prose-invert-headings:#fff;--tw-prose-invert-lead:oklch(70.7% .022 261.325);--tw-prose-invert-links:#fff;--tw-prose-invert-bold:#fff;--tw-prose-invert-counters:oklch(70.7% .022 261.325);--tw-prose-invert-bullets:oklch(44.6% .03 256.802);--tw-prose-invert-hr:oklch(37.3% .034 259.733);--tw-prose-invert-quotes:oklch(96.7% .003 264.542);--tw-prose-invert-quote-borders:oklch(37.3% .034 259.733);--tw-prose-invert-captions:oklch(70.7% .022 261.325);--tw-prose-invert-kbd:#fff;--tw-prose-invert-kbd-shadows:#ffffff1a;--tw-prose-invert-code:#fff;--tw-prose-invert-pre-code:oklch(87.2% .01 258.338);--tw-prose-invert-pre-bg:#00000080;--tw-prose-invert-th-borders:oklch(44.6% .03 256.802);--tw-prose-invert-td-borders:oklch(37.3% .034 259.733);font-size:1rem;line-height:1.75}.prose :where(picture>img):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:0;margin-bottom:0}.prose :where(li):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:.5em;margin-bottom:.5em}.prose :where(ol>li):not(:where([class~=not-prose],[class~=not-prose] *)),.prose :where(ul>li):not(:where([class~=not-prose],[class~=not-prose] *)){padding-inline-start:.375em}.prose :where(.prose>ul>li p):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:.75em;margin-bottom:.75em}.prose :where(.prose>ul>li>p:first-child):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:1.25em}.prose :where(.prose>ul>li>p:last-child):not(:where([class~=not-prose],[class~=not-prose] *)){margin-bottom:1.25em}.prose :where(.prose>ol>li>p:first-child):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:1.25em}.prose :where(.prose>ol>li>p:last-child):not(:where([class~=not-prose],[class~=not-prose] *)){margin-bottom:1.25em}.prose :where(ul ul,ul ol,ol ul,ol ol):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:.75em;margin-bottom:.75em}.prose :where(dl):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:1.25em;margin-bottom:1.25em}.prose :where(dd):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:.5em;padding-inline-start:1.625em}.prose :where(hr+*):not(:where([class~=not-prose],[class~=not-prose] *)),.prose :where(h2+*):not(:where([class~=not-prose],[class~=not-prose] *)),.prose :where(h3+*):not(:where([class~=not-prose],[class~=not-prose] *)),.prose :where(h4+*):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:0}.prose :where(thead th:first-child):not(:where([class~=not-prose],[class~=not-prose] *)){padding-inline-start:0}.prose :where(thead th:last-child):not(:where([class~=not-prose],[class~=not-prose] *)){padding-inline-end:0}.prose :where(tbody td,tfoot td):not(:where([class~=not-prose],[class~=not-prose] *)){padding-top:.571429em;padding-inline-end:.571429em;padding-bottom:.571429em;padding-inline-start:.571429em}.prose :where(tbody td:first-child,tfoot td:first-child):not(:where([class~=not-prose],[class~=not-prose] *)){padding-inline-start:0}.prose :where(tbody td:last-child,tfoot td:last-child):not(:where([class~=not-prose],[class~=not-prose] *)){padding-inline-end:0}.prose :where(figure):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:2em;margin-bottom:2em}.prose :where(.prose>:first-child):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:0}.prose :where(.prose>:last-child):not(:where([class~=not-prose],[class~=not-prose] *)){margin-bottom:0}.prose-sm{font-size:.875rem;line-height:1.71429}.prose-sm :where(p):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:1.14286em;margin-bottom:1.14286em}.prose-sm :where([class~=lead]):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:.888889em;margin-bottom:.888889em;font-size:1.28571em;line-height:1.55556}.prose-sm :where(blockquote):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:1.33333em;margin-bottom:1.33333em;padding-inline-start:1.11111em}.prose-sm :where(h1):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:0;margin-bottom:.8em;font-size:2.14286em;line-height:1.2}.prose-sm :where(h2):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:1.6em;margin-bottom:.8em;font-size:1.42857em;line-height:1.4}.prose-sm :where(h3):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:1.55556em;margin-bottom:.444444em;font-size:1.28571em;line-height:1.55556}.prose-sm :where(h4):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:1.42857em;margin-bottom:.571429em;line-height:1.42857}.prose-sm :where(img):not(:where([class~=not-prose],[class~=not-prose] *)),.prose-sm :where(picture):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:1.71429em;margin-bottom:1.71429em}.prose-sm :where(picture>img):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:0;margin-bottom:0}.prose-sm :where(video):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:1.71429em;margin-bottom:1.71429em}.prose-sm :where(kbd):not(:where([class~=not-prose],[class~=not-prose] *)){padding-top:.142857em;padding-inline-end:.357143em;padding-bottom:.142857em;border-radius:.3125rem;padding-inline-start:.357143em;font-size:.857143em}.prose-sm :where(code):not(:where([class~=not-prose],[class~=not-prose] *)){font-size:.857143em}.prose-sm :where(h2 code):not(:where([class~=not-prose],[class~=not-prose] *)){font-size:.9em}.prose-sm :where(h3 code):not(:where([class~=not-prose],[class~=not-prose] *)){font-size:.888889em}.prose-sm :where(pre):not(:where([class~=not-prose],[class~=not-prose] *)){padding-top:.666667em;padding-inline-end:1em;padding-bottom:.666667em;border-radius:.25rem;margin-top:1.66667em;margin-bottom:1.66667em;padding-inline-start:1em;font-size:.857143em;line-height:1.66667}.prose-sm :where(ol):not(:where([class~=not-prose],[class~=not-prose] *)),.prose-sm :where(ul):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:1.14286em;margin-bottom:1.14286em;padding-inline-start:1.57143em}.prose-sm :where(li):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:.285714em;margin-bottom:.285714em}.prose-sm :where(ol>li):not(:where([class~=not-prose],[class~=not-prose] *)),.prose-sm :where(ul>li):not(:where([class~=not-prose],[class~=not-prose] *)){padding-inline-start:.428571em}.prose-sm :where(.prose-sm>ul>li p):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:.571429em;margin-bottom:.571429em}.prose-sm :where(.prose-sm>ul>li>p:first-child):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:1.14286em}.prose-sm :where(.prose-sm>ul>li>p:last-child):not(:where([class~=not-prose],[class~=not-prose] *)){margin-bottom:1.14286em}.prose-sm :where(.prose-sm>ol>li>p:first-child):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:1.14286em}.prose-sm :where(.prose-sm>ol>li>p:last-child):not(:where([class~=not-prose],[class~=not-prose] *)){margin-bottom:1.14286em}.prose-sm :where(ul ul,ul ol,ol ul,ol ol):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:.571429em;margin-bottom:.571429em}.prose-sm :where(dl):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:1.14286em;margin-bottom:1.14286em}.prose-sm :where(dt):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:1.14286em}.prose-sm :where(dd):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:.285714em;padding-inline-start:1.57143em}.prose-sm :where(hr):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:2.85714em;margin-bottom:2.85714em}.prose-sm :where(hr+*):not(:where([class~=not-prose],[class~=not-prose] *)),.prose-sm :where(h2+*):not(:where([class~=not-prose],[class~=not-prose] *)),.prose-sm :where(h3+*):not(:where([class~=not-prose],[class~=not-prose] *)),.prose-sm :where(h4+*):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:0}.prose-sm :where(table):not(:where([class~=not-prose],[class~=not-prose] *)){font-size:.857143em;line-height:1.5}.prose-sm :where(thead th):not(:where([class~=not-prose],[class~=not-prose] *)){padding-inline-end:1em;padding-bottom:.666667em;padding-inline-start:1em}.prose-sm :where(thead th:first-child):not(:where([class~=not-prose],[class~=not-prose] *)){padding-inline-start:0}.prose-sm :where(thead th:last-child):not(:where([class~=not-prose],[class~=not-prose] *)){padding-inline-end:0}.prose-sm :where(tbody td,tfoot td):not(:where([class~=not-prose],[class~=not-prose] *)){padding-top:.666667em;padding-inline-end:1em;padding-bottom:.666667em;padding-inline-start:1em}.prose-sm :where(tbody td:first-child,tfoot td:first-child):not(:where([class~=not-prose],[class~=not-prose] *)){padding-inline-start:0}.prose-sm :where(tbody td:last-child,tfoot td:last-child):not(:where([class~=not-prose],[class~=not-prose] *)){padding-inline-end:0}.prose-sm :where(figure):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:1.71429em;margin-bottom:1.71429em}.prose-sm :where(figure>*):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:0;margin-bottom:0}.prose-sm :where(figcaption):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:.666667em;font-size:.857143em;line-height:1.33333}.prose-sm :where(.prose-sm>:first-child):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:0}.prose-sm :where(.prose-sm>:last-child):not(:where([class~=not-prose],[class~=not-prose] *)){margin-bottom:0}.-mt-10{margin-top:calc(var(--spacing) * -10)}.mt-0\.5{margin-top:calc(var(--spacing) * .5)}.mt-1{margin-top:var(--spacing)}.mt-2{margin-top:calc(var(--spacing) * 2)}.mt-3{margin-top:calc(var(--spacing) * 3)}.mt-4{margin-top:calc(var(--spacing) * 4)}.mt-6{margin-top:calc(var(--spacing) * 6)}.mt-8{margin-top:calc(var(--spacing) * 8)}.mt-12{margin-top:calc(var(--spacing) * 12)}.mt-16{margin-top:calc(var(--spacing) * 16)}.mr-0\.5{margin-right:calc(var(--spacing) * .5)}.mb-0{margin-bottom:0}.mb-1\.5{margin-bottom:calc(var(--spacing) * 1.5)}.mb-2{margin-bottom:calc(var(--spacing) * 2)}.mb-3{margin-bottom:calc(var(--spacing) * 3)}.mb-4{margin-bottom:calc(var(--spacing) * 4)}.mb-6{margin-bottom:calc(var(--spacing) * 6)}.mb-8{margin-bottom:calc(var(--spacing) * 8)}.mb-14{margin-bottom:calc(var(--spacing) * 14)}.ml-1{margin-left:var(--spacing)}.ml-2{margin-left:calc(var(--spacing) * 2)}.ml-auto{margin-left:auto}.box-border{box-sizing:border-box}.block{display:block}.contents{display:contents}.flex{display:flex}.grid{display:grid}.hidden{display:none}.inline{display:inline}.inline-block{display:inline-block}.inline-flex{display:inline-flex}.table{display:table}.size-3\.5{width:calc(var(--spacing) * 3.5);height:calc(var(--spacing) * 3.5)}.size-4{width:calc(var(--spacing) * 4);height:calc(var(--spacing) * 4)}.size-\[26px\]{width:26px;height:26px}.h-1\.5{height:calc(var(--spacing) * 1.5)}.h-3{height:calc(var(--spacing) * 3)}.h-4{height:calc(var(--spacing) * 4)}.h-5{height:calc(var(--spacing) * 5)}.h-6{height:calc(var(--spacing) * 6)}.h-7{height:calc(var(--spacing) * 7)}.h-8{height:calc(var(--spacing) * 8)}.h-9{height:calc(var(--spacing) * 9)}.h-12{height:calc(var(--spacing) * 12)}.h-14{height:calc(var(--spacing) * 14)}.h-16{height:calc(var(--spacing) * 16)}.h-\[1\.5px\]{height:1.5px}.h-\[1lh\]{height:1lh}.h-full{height:100%}.max-h-full{max-height:100%}.w-1\.5{width:calc(var(--spacing) * 1.5)}.w-3{width:calc(var(--spacing) * 3)}.w-4{width:calc(var(--spacing) * 4)}.w-5{width:calc(var(--spacing) * 5)}.w-8{width:calc(var(--spacing) * 8)}.w-\[16\.5rem\]{width:16.5rem}.w-\[18rem\]{width:18rem}.w-\[19rem\]{width:19rem}.w-\[28rem\]{width:28rem}.w-auto{width:auto}.w-full{width:100%}.max-w-2xl{max-width:var(--container-2xl)}.max-w-3xl{max-width:var(--container-3xl)}.max-w-\[28rem\]{max-width:28rem}.max-w-\[92rem\]{max-width:92rem}.max-w-none{max-width:none}.min-w-0{min-width:0}.min-w-4{min-width:calc(var(--spacing) * 4)}.min-w-\[42px\]{min-width:42px}.min-w-\[43px\]{min-width:43px}.min-w-\[120px\]{min-width:120px}.min-w-\[140px\]{min-width:140px}.flex-1{flex:1}.flex-none{flex:none}.shrink-0{flex-shrink:0}.grow{flex-grow:1}.-translate-x-1\/2{--tw-translate-x:calc(calc(1 / 2 * 100%) * -1);translate:var(--tw-translate-x) var(--tw-translate-y)}.-translate-y-1\/2{--tw-translate-y:calc(calc(1 / 2 * 100%) * -1);translate:var(--tw-translate-x) var(--tw-translate-y)}.transform{transform:var(--tw-rotate-x,) var(--tw-rotate-y,) var(--tw-rotate-z,) var(--tw-skew-x,) var(--tw-skew-y,)}.cursor-pointer{cursor:pointer}.flex-col{flex-direction:column}.flex-row-reverse{flex-direction:row-reverse}.flex-wrap{flex-wrap:wrap}.items-baseline{align-items:baseline}.items-center{align-items:center}.items-start{align-items:flex-start}.items-stretch{align-items:stretch}.justify-between{justify-content:space-between}.justify-center{justify-content:center}.justify-end{justify-content:flex-end}.gap-0\.5{gap:calc(var(--spacing) * .5)}.gap-1{gap:var(--spacing)}.gap-1\.5{gap:calc(var(--spacing) * 1.5)}.gap-2{gap:calc(var(--spacing) * 2)}.gap-2\.5{gap:calc(var(--spacing) * 2.5)}.gap-3{gap:calc(var(--spacing) * 3)}.gap-4{gap:calc(var(--spacing) * 4)}.gap-8{gap:calc(var(--spacing) * 8)}.gap-12{gap:calc(var(--spacing) * 12)}:where(.space-y-1>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(var(--spacing) * var(--tw-space-y-reverse));margin-block-end:calc(var(--spacing) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-2>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 2) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 2) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-2\.5>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 2.5) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 2.5) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-3>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 3) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 3) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-4>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 4) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 4) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-px>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(1px * var(--tw-space-y-reverse));margin-block-end:calc(1px * calc(1 - var(--tw-space-y-reverse)))}.gap-x-4{column-gap:calc(var(--spacing) * 4)}.gap-x-6{column-gap:calc(var(--spacing) * 6)}:where(.space-x-2\.5>:not(:last-child)){--tw-space-x-reverse:0;margin-inline-start:calc(calc(var(--spacing) * 2.5) * var(--tw-space-x-reverse));margin-inline-end:calc(calc(var(--spacing) * 2.5) * calc(1 - var(--tw-space-x-reverse)))}:where(.space-x-3>:not(:last-child)){--tw-space-x-reverse:0;margin-inline-start:calc(calc(var(--spacing) * 3) * var(--tw-space-x-reverse));margin-inline-end:calc(calc(var(--spacing) * 3) * calc(1 - var(--tw-space-x-reverse)))}:where(.space-x-4>:not(:last-child)){--tw-space-x-reverse:0;margin-inline-start:calc(calc(var(--spacing) * 4) * var(--tw-space-x-reverse));margin-inline-end:calc(calc(var(--spacing) * 4) * calc(1 - var(--tw-space-x-reverse)))}:where(.space-x-6>:not(:last-child)){--tw-space-x-reverse:0;margin-inline-start:calc(calc(var(--spacing) * 6) * var(--tw-space-x-reverse));margin-inline-end:calc(calc(var(--spacing) * 6) * calc(1 - var(--tw-space-x-reverse)))}.gap-y-1{row-gap:var(--spacing)}.self-start{align-self:flex-start}.truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.overflow-visible{overflow:visible}.overflow-x-auto{overflow-x:auto}.overflow-y-auto{overflow-y:auto}.rounded-\[var\(--radius\)\]{border-radius:var(--radius)}.rounded-full{border-radius:3.40282e38px}.rounded-lg{border-radius:var(--radius-lg)}.rounded-md{border-radius:var(--radius-md)}.border{border-style:var(--tw-border-style);border-width:1px}.border-t{border-top-style:var(--tw-border-style);border-top-width:1px}.border-b{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.border-\[rgb\(var\(--color-gray-100\)\)\]{border-color:rgb(var(--color-gray-100))}.border-\[rgb\(var\(--color-gray-200\)\/0\.7\)\]{border-color:rgb(var(--color-gray-200)/.7)}.border-\[rgb\(var\(--color-gray-500\)\/0\.08\)\]{border-color:rgb(var(--color-gray-500)/.08)}.border-\[rgb\(var\(--color-stone-200\)\)\]{border-color:rgb(var(--color-stone-200))}.bg-\[rgb\(var\(--color-background-light\)\)\]{background-color:rgb(var(--color-background-light))}.bg-\[rgb\(var\(--color-code-block-light\)\)\]{background-color:rgb(var(--color-code-block-light))}.bg-\[rgb\(var\(--color-gray-100\)\/0\.5\)\]{background-color:rgb(var(--color-gray-100)/.5)}.bg-\[rgb\(var\(--color-primary\)\)\]{background-color:rgb(var(--color-primary))}.bg-\[rgb\(var\(--color-primary-dark\)\)\]{background-color:rgb(var(--color-primary-dark))}.bg-amber-100{background-color:var(--color-amber-100)}.bg-amber-100\/50{background-color:#fef3c680}@supports (color:color-mix(in lab, red, red)){.bg-amber-100\/50{background-color:color-mix(in oklab, var(--color-amber-100) 50%, transparent)}}.bg-blue-100{background-color:var(--color-blue-100)}.bg-blue-100\/50{background-color:#dbeafe80}@supports (color:color-mix(in lab, red, red)){.bg-blue-100\/50{background-color:color-mix(in oklab, var(--color-blue-100) 50%, transparent)}}.bg-blue-400\/20{background-color:#54a2ff33}@supports (color:color-mix(in lab, red, red)){.bg-blue-400\/20{background-color:color-mix(in oklab, var(--color-blue-400) 20%, transparent)}}.bg-blue-500{background-color:var(--color-blue-500)}.bg-gray-400\/20{background-color:color-mix(in srgb, 161 161 165 20%, transparent)}@supports (color:color-mix(in lab, red, red)){.bg-gray-400\/20{background-color:color-mix(in oklab, var(--color-gray-400) 20%, transparent)}}.bg-green-100{background-color:var(--color-green-100)}.bg-green-100\/50{background-color:#dcfce780}@supports (color:color-mix(in lab, red, red)){.bg-green-100\/50{background-color:color-mix(in oklab, var(--color-green-100) 50%, transparent)}}.bg-green-400\/20{background-color:#05df7233}@supports (color:color-mix(in lab, red, red)){.bg-green-400\/20{background-color:color-mix(in oklab, var(--color-green-400) 20%, transparent)}}.bg-green-500{background-color:var(--color-green-500)}.bg-orange-100{background-color:var(--color-orange-100)}.bg-purple-400\/20{background-color:#c07eff33}@supports (color:color-mix(in lab, red, red)){.bg-purple-400\/20{background-color:color-mix(in oklab, var(--color-purple-400) 20%, transparent)}}.bg-purple-500{background-color:var(--color-purple-500)}.bg-red-100{background-color:var(--color-red-100)}.bg-red-100\/50{background-color:#ffe2e280}@supports (color:color-mix(in lab, red, red)){.bg-red-100\/50{background-color:color-mix(in oklab, var(--color-red-100) 50%, transparent)}}.bg-gradient-to-b{--tw-gradient-position:to bottom in oklab;background-image:linear-gradient(var(--tw-gradient-stops))}.from-\[rgb\(var\(--color-background-light\)\)\]{--tw-gradient-from:rgb(var(--color-background-light));--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.object-contain{object-fit:contain}.p-2{padding:calc(var(--spacing) * 2)}.px-1{padding-inline:var(--spacing)}.px-1\.5{padding-inline:calc(var(--spacing) * 1.5)}.px-2{padding-inline:calc(var(--spacing) * 2)}.px-3{padding-inline:calc(var(--spacing) * 3)}.px-4{padding-inline:calc(var(--spacing) * 4)}.px-5{padding-inline:calc(var(--spacing) * 5)}.px-12{padding-inline:calc(var(--spacing) * 12)}.py-0\.5{padding-block:calc(var(--spacing) * .5)}.py-1{padding-block:var(--spacing)}.py-1\.5{padding-block:calc(var(--spacing) * 1.5)}.py-2{padding-block:calc(var(--spacing) * 2)}.py-2\.5{padding-block:calc(var(--spacing) * 2.5)}.py-3{padding-block:calc(var(--spacing) * 3)}.py-3\.5{padding-block:calc(var(--spacing) * 3.5)}.py-4{padding-block:calc(var(--spacing) * 4)}.py-8{padding-block:calc(var(--spacing) * 8)}.pt-5{padding-top:calc(var(--spacing) * 5)}.pt-6{padding-top:calc(var(--spacing) * 6)}.pt-10{padding-top:calc(var(--spacing) * 10)}.pt-\[8\.5rem\]{padding-top:8.5rem}.pr-3{padding-right:calc(var(--spacing) * 3)}.pr-8{padding-right:calc(var(--spacing) * 8)}.pb-2\.5{padding-bottom:calc(var(--spacing) * 2.5)}.pb-3{padding-bottom:calc(var(--spacing) * 3)}.pb-4{padding-bottom:calc(var(--spacing) * 4)}.pb-10{padding-bottom:calc(var(--spacing) * 10)}.pl-3{padding-left:calc(var(--spacing) * 3)}.pl-3\.5{padding-left:calc(var(--spacing) * 3.5)}.pl-10{padding-left:calc(var(--spacing) * 10)}.text-left{text-align:left}.text-right{text-align:right}.font-mono{font-family:var(--font-mono)}.text-2xl{font-size:var(--text-2xl);line-height:var(--tw-leading,var(--text-2xl--line-height))}.text-lg{font-size:var(--text-lg);line-height:var(--tw-leading,var(--text-lg--line-height))}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.text-xl{font-size:var(--text-xl);line-height:var(--tw-leading,var(--text-xl--line-height))}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.text-\[0\.55rem\]{font-size:.55rem}.leading-5{--tw-leading:calc(var(--spacing) * 5);line-height:calc(var(--spacing) * 5)}.leading-6{--tw-leading:calc(var(--spacing) * 6);line-height:calc(var(--spacing) * 6)}.leading-\[1\.35rem\]{--tw-leading:1.35rem;line-height:1.35rem}.leading-none{--tw-leading:1;line-height:1}.leading-tight{--tw-leading:var(--leading-tight);line-height:var(--leading-tight)}.font-bold{--tw-font-weight:var(--font-weight-bold);font-weight:var(--font-weight-bold)}.font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.font-normal{--tw-font-weight:var(--font-weight-normal);font-weight:var(--font-weight-normal)}.font-semibold{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.tracking-\[0\.12em\]{--tw-tracking:.12em;letter-spacing:.12em}.tracking-\[0\.14em\]{--tw-tracking:.14em;letter-spacing:.14em}.tracking-tight{--tw-tracking:var(--tracking-tight);letter-spacing:var(--tracking-tight)}.break-words{overflow-wrap:break-word}.\[word-break\:break-word\]{word-break:break-word}.break-all{word-break:break-all}.whitespace-nowrap{white-space:nowrap}.whitespace-pre{white-space:pre}.text-\[rgb\(var\(--color-gray-400\)\)\]{color:rgb(var(--color-gray-400))}.text-\[rgb\(var\(--color-gray-500\)\)\]{color:rgb(var(--color-gray-500))}.text-\[rgb\(var\(--color-gray-600\)\)\]{color:rgb(var(--color-gray-600))}.text-\[rgb\(var\(--color-gray-700\)\)\]{color:rgb(var(--color-gray-700))}.text-\[rgb\(var\(--color-gray-800\)\)\]{color:rgb(var(--color-gray-800))}.text-\[rgb\(var\(--color-gray-900\)\)\]{color:rgb(var(--color-gray-900))}.text-\[rgb\(var\(--color-primary\)\)\]{color:rgb(var(--color-primary))}.text-\[rgb\(var\(--color-primary-ink\)\)\]{color:rgb(var(--color-primary-ink))}.text-\[rgb\(var\(--color-stone-400\)\)\]{color:rgb(var(--color-stone-400))}.text-\[rgb\(var\(--color-stone-500\)\)\]{color:rgb(var(--color-stone-500))}.text-\[rgb\(var\(--color-stone-600\)\)\]{color:rgb(var(--color-stone-600))}.text-\[rgb\(var\(--color-stone-950\)\)\]{color:rgb(var(--color-stone-950))}.text-amber-600{color:var(--color-amber-600)}.text-amber-900{color:var(--color-amber-900)}.text-blue-600{color:var(--color-blue-600)}.text-blue-700{color:var(--color-blue-700)}.text-blue-800{color:var(--color-blue-800)}.text-gray-700{color:var(--color-gray-700)}.text-green-600{color:var(--color-green-600)}.text-green-700{color:var(--color-green-700)}.text-green-800{color:var(--color-green-800)}.text-orange-900{color:var(--color-orange-900)}.text-purple-700{color:var(--color-purple-700)}.text-red-600{color:var(--color-red-600)}.text-red-800{color:var(--color-red-800)}.text-white{color:var(--color-white)}.uppercase{text-transform:uppercase}.ordinal{--tw-ordinal:ordinal;font-variant-numeric:var(--tw-ordinal,) var(--tw-slashed-zero,) var(--tw-numeric-figure,) var(--tw-numeric-spacing,) var(--tw-numeric-fraction,)}.no-underline{text-decoration-line:none}.antialiased{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.opacity-0{opacity:0}.opacity-90{opacity:.9}.shadow-lg{--tw-shadow:0 10px 15px -3px var(--tw-shadow-color,#0000001a), 0 4px 6px -4px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.ring-1{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.ring-\[rgb\(var\(--color-gray-400\)\/0\.3\)\]{--tw-ring-color:rgb(var(--color-gray-400)/.3)}.outline{outline-style:var(--tw-outline-style);outline-width:1px}.outline-0{outline-style:var(--tw-outline-style);outline-width:0}.backdrop-blur{--tw-backdrop-blur:blur(8px);-webkit-backdrop-filter:var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,);backdrop-filter:var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,)}.transition-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-opacity{transition-property:opacity;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.prose-gray{--tw-prose-body:oklch(37.3% .034 259.733);--tw-prose-headings:oklch(21% .034 264.665);--tw-prose-lead:oklch(44.6% .03 256.802);--tw-prose-links:oklch(21% .034 264.665);--tw-prose-bold:oklch(21% .034 264.665);--tw-prose-counters:oklch(55.1% .027 264.364);--tw-prose-bullets:oklch(87.2% .01 258.338);--tw-prose-hr:oklch(92.8% .006 264.531);--tw-prose-quotes:oklch(21% .034 264.665);--tw-prose-quote-borders:oklch(92.8% .006 264.531);--tw-prose-captions:oklch(55.1% .027 264.364);--tw-prose-kbd:oklch(21% .034 264.665);--tw-prose-kbd-shadows:oklab(21% -.00316127 -.0338527/.1);--tw-prose-code:oklch(21% .034 264.665);--tw-prose-pre-code:oklch(92.8% .006 264.531);--tw-prose-pre-bg:oklch(27.8% .033 256.848);--tw-prose-th-borders:oklch(87.2% .01 258.338);--tw-prose-td-borders:oklch(92.8% .006 264.531);--tw-prose-invert-body:oklch(87.2% .01 258.338);--tw-prose-invert-headings:#fff;--tw-prose-invert-lead:oklch(70.7% .022 261.325);--tw-prose-invert-links:#fff;--tw-prose-invert-bold:#fff;--tw-prose-invert-counters:oklch(70.7% .022 261.325);--tw-prose-invert-bullets:oklch(44.6% .03 256.802);--tw-prose-invert-hr:oklch(37.3% .034 259.733);--tw-prose-invert-quotes:oklch(96.7% .003 264.542);--tw-prose-invert-quote-borders:oklch(37.3% .034 259.733);--tw-prose-invert-captions:oklch(70.7% .022 261.325);--tw-prose-invert-kbd:#fff;--tw-prose-invert-kbd-shadows:#ffffff1a;--tw-prose-invert-code:#fff;--tw-prose-invert-pre-code:oklch(87.2% .01 258.338);--tw-prose-invert-pre-bg:#00000080;--tw-prose-invert-th-borders:oklch(44.6% .03 256.802);--tw-prose-invert-td-borders:oklch(37.3% .034 259.733)}.select-none{-webkit-user-select:none;user-select:none}.\[text-shadow\:-0\.2px_0_0_currentColor\,0\.2px_0_0_currentColor\]{text-shadow:-.2px 0,.2px 0}@media (hover:hover){.group-hover\:bg-\[rgb\(var\(--color-gray-200\)\)\]:is(:where(.group):hover *){background-color:rgb(var(--color-gray-200))}.group-hover\:bg-\[rgb\(var\(--color-stone-200\)\/0\.5\)\]:is(:where(.group):hover *){background-color:rgb(var(--color-stone-200)/.5)}.group-hover\:text-\[rgb\(var\(--color-primary\)\)\]:is(:where(.group):hover *){color:rgb(var(--color-primary))}.group-hover\:text-\[rgb\(var\(--color-primary-ink\)\)\]:is(:where(.group):hover *){color:rgb(var(--color-primary-ink))}.group-hover\:opacity-90:is(:where(.group):hover *){opacity:.9}.group-hover\/copy\:text-\[rgb\(var\(--color-stone-500\)\)\]:is(:where(.group\/copy):hover *){color:rgb(var(--color-stone-500))}.peer-hover\:opacity-100:is(:where(.peer):hover~*){opacity:1}}.first\:mt-0:first-child{margin-top:0}@media (hover:hover){.hover\:border-\[rgb\(var\(--color-primary\)\/0\.4\)\]:hover{border-color:rgb(var(--color-primary)/.4)}.hover\:bg-\[rgb\(var\(--color-stone-100\)\)\]:hover{background-color:rgb(var(--color-stone-100))}.hover\:text-\[rgb\(var\(--color-gray-600\)\)\]:hover{color:rgb(var(--color-gray-600))}.hover\:text-\[rgb\(var\(--color-gray-700\)\)\]:hover{color:rgb(var(--color-gray-700))}.hover\:text-\[rgb\(var\(--color-gray-800\)\)\]:hover{color:rgb(var(--color-gray-800))}.hover\:text-\[rgb\(var\(--color-gray-900\)\)\]:hover{color:rgb(var(--color-gray-900))}.hover\:underline:hover{text-decoration-line:underline}.hover\:ring-\[rgb\(var\(--color-gray-600\)\/0\.3\)\]:hover{--tw-ring-color:rgb(var(--color-gray-600)/.3)}}@media (width>=40rem){.sm\:flex-row{flex-direction:row}.sm\:items-center{align-items:center}.sm\:text-3xl{font-size:var(--text-3xl);line-height:var(--tw-leading,var(--text-3xl--line-height))}}@media (width>=64rem){.lg\:sticky{position:sticky}.lg\:mx-0{margin-inline:0}.lg\:mt-8{margin-top:calc(var(--spacing) * 8)}.lg\:-ml-12{margin-left:calc(var(--spacing) * -12)}.lg\:block{display:block}.lg\:flex{display:flex}.lg\:hidden{display:none}.lg\:flex-row{flex-direction:row}.lg\:px-8{padding-inline:calc(var(--spacing) * 8)}.lg\:px-12{padding-inline:calc(var(--spacing) * 12)}.lg\:pt-10{padding-top:calc(var(--spacing) * 10)}.lg\:pl-\[23\.7rem\]{padding-left:23.7rem}}@media (width>=80rem){.xl\:block{display:block}.xl\:flex{display:flex}.xl\:hidden{display:none}.xl\:w-\[calc\(100\%-28rem\)\]{width:calc(100% - 28rem)}.xl\:flex-col{flex-direction:column}.xl\:flex-row{flex-direction:row}}.dark\:block:where(.dark,.dark *){display:block}.dark\:hidden:where(.dark,.dark *){display:none}.dark\:border-\[rgb\(255_255_255\/0\.1\)\]:where(.dark,.dark *){border-color:#ffffff1a}.dark\:border-\[rgb\(var\(--color-border-dark-subtle\)\/0\.1\)\]:where(.dark,.dark *){border-color:rgb(var(--color-border-dark-subtle)/.1)}.dark\:border-\[rgb\(var\(--color-gray-300\)\/0\.06\)\]:where(.dark,.dark *){border-color:rgb(var(--color-gray-300)/.06)}.dark\:border-\[rgb\(var\(--color-gray-300\)\/0\.08\)\]:where(.dark,.dark *){border-color:rgb(var(--color-gray-300)/.08)}.dark\:border-\[rgb\(var\(--color-gray-800\)\)\]:where(.dark,.dark *){border-color:rgb(var(--color-gray-800))}.dark\:border-\[rgb\(var\(--color-gray-800\)\/0\.5\)\]:where(.dark,.dark *){border-color:rgb(var(--color-gray-800)/.5)}.dark\:bg-\[rgb\(var\(--color-background-dark\)\)\]:where(.dark,.dark *){background-color:rgb(var(--color-background-dark))}.dark\:bg-\[rgb\(var\(--color-code-block-dark\)\)\]:where(.dark,.dark *){background-color:rgb(var(--color-code-block-dark))}.dark\:bg-\[rgb\(var\(--color-primary-light\)\)\]:where(.dark,.dark *){background-color:rgb(var(--color-primary-light))}.dark\:bg-\[rgb\(var\(--color-stone-900\)\)\]:where(.dark,.dark *){background-color:rgb(var(--color-stone-900))}.dark\:bg-\[rgb\(var\(--color-surface-dark-tint\)\/0\.05\)\]:where(.dark,.dark *){background-color:rgb(var(--color-surface-dark-tint)/.05)}.dark\:bg-amber-400\/10:where(.dark,.dark *){background-color:#fcbb001a}@supports (color:color-mix(in lab, red, red)){.dark\:bg-amber-400\/10:where(.dark,.dark *){background-color:color-mix(in oklab, var(--color-amber-400) 10%, transparent)}}.dark\:bg-blue-400:where(.dark,.dark *){background-color:var(--color-blue-400)}.dark\:bg-blue-400\/10:where(.dark,.dark *){background-color:#54a2ff1a}@supports (color:color-mix(in lab, red, red)){.dark\:bg-blue-400\/10:where(.dark,.dark *){background-color:color-mix(in oklab, var(--color-blue-400) 10%, transparent)}}.dark\:bg-blue-400\/20:where(.dark,.dark *){background-color:#54a2ff33}@supports (color:color-mix(in lab, red, red)){.dark\:bg-blue-400\/20:where(.dark,.dark *){background-color:color-mix(in oklab, var(--color-blue-400) 20%, transparent)}}.dark\:bg-green-400:where(.dark,.dark *){background-color:var(--color-green-400)}.dark\:bg-green-400\/10:where(.dark,.dark *){background-color:#05df721a}@supports (color:color-mix(in lab, red, red)){.dark\:bg-green-400\/10:where(.dark,.dark *){background-color:color-mix(in oklab, var(--color-green-400) 10%, transparent)}}.dark\:bg-green-400\/20:where(.dark,.dark *){background-color:#05df7233}@supports (color:color-mix(in lab, red, red)){.dark\:bg-green-400\/20:where(.dark,.dark *){background-color:color-mix(in oklab, var(--color-green-400) 20%, transparent)}}.dark\:bg-orange-400\/20:where(.dark,.dark *){background-color:#ff8b1a33}@supports (color:color-mix(in lab, red, red)){.dark\:bg-orange-400\/20:where(.dark,.dark *){background-color:color-mix(in oklab, var(--color-orange-400) 20%, transparent)}}.dark\:bg-purple-400:where(.dark,.dark *){background-color:var(--color-purple-400)}.dark\:bg-purple-400\/20:where(.dark,.dark *){background-color:#c07eff33}@supports (color:color-mix(in lab, red, red)){.dark\:bg-purple-400\/20:where(.dark,.dark *){background-color:color-mix(in oklab, var(--color-purple-400) 20%, transparent)}}.dark\:bg-red-400\/10:where(.dark,.dark *){background-color:#ff65681a}@supports (color:color-mix(in lab, red, red)){.dark\:bg-red-400\/10:where(.dark,.dark *){background-color:color-mix(in oklab, var(--color-red-400) 10%, transparent)}}.dark\:bg-red-400\/20:where(.dark,.dark *){background-color:#ff656833}@supports (color:color-mix(in lab, red, red)){.dark\:bg-red-400\/20:where(.dark,.dark *){background-color:color-mix(in oklab, var(--color-red-400) 20%, transparent)}}.dark\:bg-yellow-400\/20:where(.dark,.dark *){background-color:#fac80033}@supports (color:color-mix(in lab, red, red)){.dark\:bg-yellow-400\/20:where(.dark,.dark *){background-color:color-mix(in oklab, var(--color-yellow-400) 20%, transparent)}}.dark\:from-\[rgb\(var\(--color-background-dark\)\)\]:where(.dark,.dark *){--tw-gradient-from:rgb(var(--color-background-dark));--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.dark\:text-\[rgb\(255_255_255\/0\.4\)\]:where(.dark,.dark *){color:#fff6}.dark\:text-\[rgb\(var\(--color-gray-50\)\)\]:where(.dark,.dark *){color:rgb(var(--color-gray-50))}.dark\:text-\[rgb\(var\(--color-gray-200\)\)\]:where(.dark,.dark *){color:rgb(var(--color-gray-200))}.dark\:text-\[rgb\(var\(--color-gray-300\)\)\]:where(.dark,.dark *){color:rgb(var(--color-gray-300))}.dark\:text-\[rgb\(var\(--color-gray-400\)\)\]:where(.dark,.dark *){color:rgb(var(--color-gray-400))}.dark\:text-\[rgb\(var\(--color-gray-500\)\)\]:where(.dark,.dark *){color:rgb(var(--color-gray-500))}.dark\:text-\[rgb\(var\(--color-primary-light\)\)\]:where(.dark,.dark *){color:rgb(var(--color-primary-light))}.dark\:text-\[rgb\(var\(--color-stone-50\)\)\]:where(.dark,.dark *){color:rgb(var(--color-stone-50))}.dark\:text-\[rgb\(var\(--color-stone-400\)\)\]:where(.dark,.dark *){color:rgb(var(--color-stone-400))}.dark\:text-amber-300:where(.dark,.dark *){color:var(--color-amber-300)}.dark\:text-blue-300:where(.dark,.dark *){color:var(--color-blue-300)}.dark\:text-blue-400:where(.dark,.dark *){color:var(--color-blue-400)}.dark\:text-gray-400:where(.dark,.dark *){color:var(--color-gray-400)}.dark\:text-green-300:where(.dark,.dark *){color:var(--color-green-300)}.dark\:text-green-400:where(.dark,.dark *){color:var(--color-green-400)}.dark\:text-orange-300:where(.dark,.dark *){color:var(--color-orange-300)}.dark\:text-purple-400:where(.dark,.dark *){color:var(--color-purple-400)}.dark\:text-red-300:where(.dark,.dark *){color:var(--color-red-300)}.dark\:text-yellow-300:where(.dark,.dark *){color:var(--color-yellow-300)}.dark\:ring-\[rgb\(var\(--color-gray-600\)\/0\.3\)\]:where(.dark,.dark *){--tw-ring-color:rgb(var(--color-gray-600)/.3)}.dark\:brightness-110:where(.dark,.dark *){--tw-brightness:brightness(110%);filter:var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,)}.dark\:prose-invert:where(.dark,.dark *){--tw-prose-body:var(--tw-prose-invert-body);--tw-prose-headings:var(--tw-prose-invert-headings);--tw-prose-lead:var(--tw-prose-invert-lead);--tw-prose-links:var(--tw-prose-invert-links);--tw-prose-bold:var(--tw-prose-invert-bold);--tw-prose-counters:var(--tw-prose-invert-counters);--tw-prose-bullets:var(--tw-prose-invert-bullets);--tw-prose-hr:var(--tw-prose-invert-hr);--tw-prose-quotes:var(--tw-prose-invert-quotes);--tw-prose-quote-borders:var(--tw-prose-invert-quote-borders);--tw-prose-captions:var(--tw-prose-invert-captions);--tw-prose-kbd:var(--tw-prose-invert-kbd);--tw-prose-kbd-shadows:var(--tw-prose-invert-kbd-shadows);--tw-prose-code:var(--tw-prose-invert-code);--tw-prose-pre-code:var(--tw-prose-invert-pre-code);--tw-prose-pre-bg:var(--tw-prose-invert-pre-bg);--tw-prose-th-borders:var(--tw-prose-invert-th-borders);--tw-prose-td-borders:var(--tw-prose-invert-td-borders)}@media (hover:hover){.dark\:group-hover\:bg-\[rgb\(var\(--color-gray-700\)\)\]:where(.dark,.dark *):is(:where(.group):hover *){background-color:rgb(var(--color-gray-700))}.dark\:group-hover\:bg-\[rgb\(var\(--color-stone-700\)\/0\.7\)\]:where(.dark,.dark *):is(:where(.group):hover *){background-color:rgb(var(--color-stone-700)/.7)}.dark\:group-hover\:text-\[rgb\(var\(--color-primary-light\)\)\]:where(.dark,.dark *):is(:where(.group):hover *){color:rgb(var(--color-primary-light))}.dark\:group-hover\/copy\:text-\[rgb\(255_255_255\/0\.6\)\]:where(.dark,.dark *):is(:where(.group\/copy):hover *){color:#fff9}.dark\:hover\:border-\[rgb\(var\(--color-primary-light\)\/0\.3\)\]:where(.dark,.dark *):hover{border-color:rgb(var(--color-primary-light)/.3)}.dark\:hover\:bg-\[rgb\(255_255_255\/0\.05\)\]:where(.dark,.dark *):hover{background-color:#ffffff0d}.dark\:hover\:text-\[rgb\(var\(--color-gray-200\)\)\]:where(.dark,.dark *):hover{color:rgb(var(--color-gray-200))}.dark\:hover\:text-\[rgb\(var\(--color-gray-300\)\)\]:where(.dark,.dark *):hover{color:rgb(var(--color-gray-300))}.dark\:hover\:ring-\[rgb\(var\(--color-gray-500\)\/0\.3\)\]:where(.dark,.dark *):hover{--tw-ring-color:rgb(var(--color-gray-500)/.3)}.dark\:hover\:brightness-125:where(.dark,.dark *):hover{--tw-brightness:brightness(125%);filter:var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,)}}}@property --tw-translate-x{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-y{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-z{syntax:"*";inherits:false;initial-value:0}@property --tw-rotate-x{syntax:"*";inherits:false}@property --tw-rotate-y{syntax:"*";inherits:false}@property --tw-rotate-z{syntax:"*";inherits:false}@property --tw-skew-x{syntax:"*";inherits:false}@property --tw-skew-y{syntax:"*";inherits:false}@property --tw-space-y-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-space-x-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-gradient-position{syntax:"*";inherits:false}@property --tw-gradient-from{syntax:"";inherits:false;initial-value:#0000}@property --tw-gradient-via{syntax:"";inherits:false;initial-value:#0000}@property --tw-gradient-to{syntax:"";inherits:false;initial-value:#0000}@property --tw-gradient-stops{syntax:"*";inherits:false}@property --tw-gradient-via-stops{syntax:"*";inherits:false}@property --tw-gradient-from-position{syntax:"";inherits:false;initial-value:0%}@property --tw-gradient-via-position{syntax:"";inherits:false;initial-value:50%}@property --tw-gradient-to-position{syntax:"";inherits:false;initial-value:100%}@property --tw-leading{syntax:"*";inherits:false}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-tracking{syntax:"*";inherits:false}@property --tw-ordinal{syntax:"*";inherits:false}@property --tw-slashed-zero{syntax:"*";inherits:false}@property --tw-numeric-figure{syntax:"*";inherits:false}@property --tw-numeric-spacing{syntax:"*";inherits:false}@property --tw-numeric-fraction{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-outline-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-backdrop-blur{syntax:"*";inherits:false}@property --tw-backdrop-brightness{syntax:"*";inherits:false}@property --tw-backdrop-contrast{syntax:"*";inherits:false}@property --tw-backdrop-grayscale{syntax:"*";inherits:false}@property --tw-backdrop-hue-rotate{syntax:"*";inherits:false}@property --tw-backdrop-invert{syntax:"*";inherits:false}@property --tw-backdrop-opacity{syntax:"*";inherits:false}@property --tw-backdrop-saturate{syntax:"*";inherits:false}@property --tw-backdrop-sepia{syntax:"*";inherits:false}@property --tw-blur{syntax:"*";inherits:false}@property --tw-brightness{syntax:"*";inherits:false}@property --tw-contrast{syntax:"*";inherits:false}@property --tw-grayscale{syntax:"*";inherits:false}@property --tw-hue-rotate{syntax:"*";inherits:false}@property --tw-invert{syntax:"*";inherits:false}@property --tw-opacity{syntax:"*";inherits:false}@property --tw-saturate{syntax:"*";inherits:false}@property --tw-sepia{syntax:"*";inherits:false}@property --tw-drop-shadow{syntax:"*";inherits:false}@property --tw-drop-shadow-color{syntax:"*";inherits:false}@property --tw-drop-shadow-alpha{syntax:"";inherits:false;initial-value:100%}@property --tw-drop-shadow-size{syntax:"*";inherits:false} +/*$vite$:1*/ +/** + * Sourcey — Component styles. + * + * Layout and OpenAPI components use Tailwind classes in .tsx files. + * Markdown-generated components (code blocks, cards, steps, accordions, + * callouts, tabs) use semantic class names styled here — no Tailwind + * utilities in generated HTML. + */ + +/* ── Page Description (display font) ─────────────────────────────── */ + +#sourcey .page-description { + font-family: ui-serif, Georgia, Cambria, "Times New Roman", serif; + font-size: 1.125rem; + line-height: 1.35; + font-style: italic; + color: rgb(var(--color-gray-600)); +} +@media (min-width: 1024px) { + #sourcey .page-description { + font-size: 1.375rem; + line-height: 1.4; + } +} +.dark #sourcey .page-description { + color: rgb(var(--color-gray-400)); +} + +/* ── Page Top Gradient ────────────────────────────────────────────── */ + +#sourcey #page::before { + content: ""; + position: fixed; + top: 0; + left: 0; + right: 0; + height: 400px; + background: linear-gradient(to bottom, rgb(var(--color-primary) / 0.03), transparent); + pointer-events: none; + z-index: -1; +} +.dark #sourcey #page::before { + background: none; +} + +/* ── Scroll Offset (clears fixed navbar on anchor clicks) ──────────── */ + +[data-traverse-target], +h1[id], h2[id], h3[id], h4[id], h5[id], h6[id] { + scroll-margin-top: var(--header-height, 7rem); +} + +/* ── Focus ─────────────────────────────────────────────────────────── */ + +#sourcey button:focus-visible { + outline: 2px solid rgb(var(--color-primary)); + outline-offset: 2px; +} + +/* ── Shiki Dual-Theme (defaultColor: false) ───────────────────────── */ +/* Shiki outputs --shiki-light and --shiki-dark CSS vars on each span. */ +/* Light mode: use --shiki-light. Dark mode: use --shiki-dark. */ + +.shiki, +.shiki span { + color: var(--shiki-light); + background-color: transparent !important; +} + +.dark .shiki, +.dark .shiki span { + color: var(--shiki-dark); +} + +.shiki pre { + background-color: transparent !important; + margin: 0; +} + +.shiki code { + font-family: inherit; + background: transparent; + border: none; + padding: 0; +} + +/* ── Responsive Tables ────────────────────────────────────────────── */ + +#sourcey .table-wrap { + overflow-x: auto; + -webkit-overflow-scrolling: touch; +} +#sourcey .table-wrap table { + margin: 0; +} +#sourcey .prose :where(thead th):not(:where([class~=not-prose],[class~=not-prose] *)) { + padding-top: .571429em; +} + +/* ── Prose Video (::video directive) ──────────────────────────────── */ + +#sourcey .prose-video { + position: relative; + width: 100%; + padding-bottom: 56.25%; /* 16:9 */ + margin: 1.5rem 0; + border-radius: var(--radius); + overflow: hidden; +} +#sourcey .prose-video iframe, +#sourcey .prose-video video { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; +} + +/* ── Prose Iframe (::iframe directive) ────────────────────────────── */ + +#sourcey .prose-iframe { + width: 100%; + margin: 1.5rem 0; + border-radius: var(--radius); + overflow: hidden; + border: 1px solid rgb(var(--color-stone-950) / 0.1); +} +.dark #sourcey .prose-iframe { + border-color: rgb(255 255 255 / 0.1); +} +#sourcey .prose-iframe iframe { + width: 100%; + height: 100%; + display: block; +} + +/* ── Inline Code (not-prose containers lose Tailwind prose styling) ── */ + +#sourcey .not-prose :not(pre) > code { + font-size: 0.875em; + font-weight: 600; + color: var(--tw-prose-code); +} +#sourcey .not-prose :not(pre) > code::before, +#sourcey .not-prose :not(pre) > code::after { + content: "`"; +} + +/* ── Prose Code Block (fenced code in markdown pages) ─────────────── */ + +#sourcey .prose-code-block { + position: relative; + border-radius: var(--radius); + border: 1px solid rgb(var(--color-stone-950) / 0.1); + margin: 1.25rem 0 2rem; + overflow: hidden; + color: rgb(var(--color-stone-950)); +} +.dark #sourcey .prose-code-block { + border-color: rgb(255 255 255 / 0.1); + color: rgb(var(--color-stone-50)); +} + +#sourcey .prose-code-copy { + position: absolute; + top: 0.75rem; + right: 1rem; + z-index: 10; +} + +#sourcey .prose-code-copy .copy-btn { + display: flex; + align-items: center; + justify-content: center; + width: 26px; + height: 26px; + border-radius: 0.375rem; + border: none; + background: transparent; + cursor: pointer; + color: rgb(var(--color-stone-400)); + transition: color 0.15s; +} +#sourcey .prose-code-copy .copy-btn:hover { + color: rgb(var(--color-stone-500)); +} +.dark #sourcey .prose-code-copy .copy-btn { + color: rgb(255 255 255 / 0.4); +} +.dark #sourcey .prose-code-copy .copy-btn:hover { + color: rgb(255 255 255 / 0.6); +} + +#sourcey .prose-code-copy .copy-btn svg { + width: 1rem; + height: 1rem; +} + +#sourcey .prose-code-content { + padding: 0.875rem 1rem; + border-radius: var(--radius); + background: rgb(var(--color-code-block-light)); + overflow-x: auto; + font-variant-ligatures: none; +} +.dark #sourcey .prose-code-content { + background: rgb(var(--color-code-block-dark)); +} + +#sourcey .prose-code-content pre { + margin: 0; + font-family: var(--font-mono); + font-size: 0.875rem; + line-height: 1.5rem; + white-space: pre; +} + +/* ── Nav Links ────────────────────────────────────────────────────── */ + +#sourcey .nav-group-label { + padding: 0 0.75rem 0.25rem 1rem; + margin-bottom: 0.625rem; + font-size: inherit; + font-weight: 600; + color: rgb(var(--color-gray-900)); +} +.dark #sourcey .nav-group-label { + color: rgb(var(--color-gray-200)); +} + +#sourcey .nav-tab-label { + display: block; + padding: 0.5rem 0.75rem 0.25rem 1rem; + font-size: 0.75rem; + font-weight: 600; + text-transform: uppercase; + letter-spacing: 0.05em; + color: rgb(var(--color-gray-400)); +} +.dark #sourcey .nav-tab-label { + color: rgb(var(--color-gray-500)); +} + +#sourcey .nav-link { + display: flex; + align-items: flex-start; + padding: 0.375rem 0.75rem 0.375rem 1rem; + gap: 0.75rem; + cursor: pointer; + text-align: left; + overflow-wrap: break-word; + hyphens: auto; + border-radius: 0.75rem; + width: 100%; + color: rgb(var(--color-gray-700)); + transition: color 0.15s, background-color 0.15s; +} +.dark #sourcey .nav-link { + color: rgb(var(--color-gray-400)); +} +#sourcey .nav-link:hover { + color: rgb(var(--color-gray-900)); + background: rgb(var(--color-gray-100) / 0.6); +} +.dark #sourcey .nav-link:hover { + color: rgb(var(--color-gray-300)); + background: rgb(var(--color-gray-800) / 0.4); +} +#sourcey .nav-link.active { + color: rgb(var(--color-primary-ink)); + background: rgb(var(--color-primary) / 0.08); + text-shadow: -0.2px 0 0 currentColor, 0.2px 0 0 currentColor; +} +.dark #sourcey .nav-link.active { + color: rgb(var(--color-primary-light)); + background: rgb(var(--color-primary-light) / 0.08); +} + +/* ── TOC Active State ─────────────────────────────────────────────── */ + +#sourcey #toc .toc-item { + border-left: 2px solid rgb(var(--color-gray-200)); + padding-left: 0.75rem; + transition: color 0.15s, border-color 0.15s; +} +#sourcey #toc ul ul .toc-item { + margin-left: 0.75rem; + border-left: none; +} +.dark #sourcey #toc .toc-item { + border-left-color: rgb(var(--color-gray-700)); +} +#sourcey #toc .toc-item.active { + color: rgb(var(--color-primary-ink)); + border-left-color: rgb(var(--color-primary-ink)); + font-weight: 500; +} +.dark #sourcey #toc .toc-item.active { + color: rgb(var(--color-primary-light)); + border-left-color: rgb(var(--color-primary-light)); +} + +/* ── Code Block Panels (language dropdown + response tabs) ─────────── */ + +#sourcey .code-lang-panel { display: none; } +#sourcey .code-lang-panel.active { display: block; } + +#sourcey .lang-icon { + width: 0.875rem; + height: 0.875rem; + flex-shrink: 0; + vertical-align: -0.125rem; +} + +#sourcey .lang-icon[data-lang] { + display: inline-block; + background: currentColor; + -webkit-mask-size: contain; + mask-size: contain; + -webkit-mask-repeat: no-repeat; + mask-repeat: no-repeat; + -webkit-mask-position: center; + mask-position: center; +} + +#sourcey .response-panel { display: none; } +#sourcey .response-panel.active { display: block; } + +/* ── Response Tabs (status code tabs on code block) ───────────────── */ + +#sourcey .response-tab { + color: rgb(var(--color-gray-500)); + transition: color 0.15s; +} +.dark #sourcey .response-tab { + color: rgb(var(--color-gray-400)); +} + +#sourcey .response-tab.active { + color: rgb(var(--color-primary-ink)); +} +.dark #sourcey .response-tab.active { + color: rgb(var(--color-primary-light)); +} + +/* Active response tab underline */ +#sourcey .response-tab.active::after { + content: ''; + position: absolute; + right: 0; + bottom: -0.375rem; + left: 0; + height: 2px; + border-radius: 9999px; + background: rgb(var(--color-primary)); +} +.dark #sourcey .response-tab.active::after { + background: rgb(var(--color-primary-light)); +} + +/* ── Copy Button Feedback ─────────────────────────────────────────── */ + +#sourcey .copy-btn.copied { + color: rgb(var(--color-success)); +} + +/* ── Schema Utilities (used by SchemaView.tsx) ─────────────────────── */ + +/* ── Collapsible child attributes ── */ + +#sourcey .schema-expandable { + margin-top: 1rem; + border: 1px solid rgb(var(--color-gray-200) / 0.7); + border-radius: 0.75rem; +} +.dark #sourcey .schema-expandable { + border-color: rgb(255 255 255 / 0.1); +} + +#sourcey .schema-expandable-toggle { + display: flex; + align-items: center; + gap: 0.75rem; + padding: 0.75rem 1rem; + font-size: 0.875rem; + font-weight: 400; + color: rgb(var(--color-gray-600)); + cursor: pointer; + list-style: none; + user-select: none; +} +#sourcey .schema-expandable-toggle::-webkit-details-marker { + display: none; +} +.dark #sourcey .schema-expandable-toggle { + color: rgb(var(--color-gray-300)); +} +#sourcey .schema-expandable-toggle:hover { + background: rgb(var(--color-gray-100) / 0.5); + color: rgb(var(--color-gray-900)); + border-radius: 0.75rem; +} +.dark #sourcey .schema-expandable-toggle:hover { + background: rgb(255 255 255 / 0.05); + color: rgb(var(--color-gray-200)); +} + +#sourcey .schema-expandable-icon { + width: 0.625rem; + height: 0.625rem; + flex-shrink: 0; + transition: transform 75ms; + color: rgb(var(--color-gray-400)); +} +#sourcey details[open] > .schema-expandable-toggle > .schema-expandable-icon { + transform: rotate(90deg); +} + +#sourcey .schema-expandable-content { + padding: 0 1rem 0.5rem; + border-top: 1px solid rgb(var(--color-gray-100)); +} +.dark #sourcey .schema-expandable-content { + border-top-color: rgb(255 255 255 / 0.1); +} + +/* Legacy schema-nested — kept for variant nesting */ +#sourcey .schema-nested { + padding-left: 1rem; + border-left: 2px solid rgb(var(--color-gray-200)); + margin-top: 0.25rem; + margin-bottom: 0.25rem; +} +.dark #sourcey .schema-nested { + border-left-color: rgb(var(--color-gray-800)); +} + +#sourcey .schema-variant-option { + padding-left: 1rem; + border-left: 2px solid rgb(var(--color-gray-200)); + margin-bottom: 0.5rem; +} +.dark #sourcey .schema-variant-option { + border-left-color: rgb(var(--color-gray-800)); +} + +#sourcey .schema-variant-label { + font-size: 0.75rem; + font-weight: 600; + letter-spacing: 0.05em; + color: rgb(var(--color-gray-400)); + margin-bottom: 0.25rem; +} + +/* ── Type Display (used by SchemaDatatype.tsx) ─────────────────────── */ + +#sourcey .json-property-type { + display: inline-flex; + align-items: center; + font-style: normal; + font-weight: 500; + font-size: 0.75rem; + line-height: 1; + white-space: nowrap; + color: rgb(var(--color-gray-600)); + background: rgb(var(--color-gray-100) / 0.5); + padding: 0.25rem 0.5rem; + border-radius: 0.375rem; +} +.dark #sourcey .json-property-type { + background: rgb(var(--color-surface-dark-tint) / 0.05); + color: rgb(var(--color-gray-200)); +} + +#sourcey .json-property-format { + font-size: 0.75rem; + color: rgb(var(--color-gray-400)); +} + +#sourcey .json-property-enum { + display: inline-flex; + align-items: baseline; + gap: 0.25rem; + flex-wrap: wrap; +} + +#sourcey .json-property-enum-item, +#sourcey .json-property-default-value, +#sourcey .json-property-range { + display: inline-flex; + align-items: center; + font-size: 0.6875rem; + font-family: var(--font-mono); + line-height: 1; + white-space: nowrap; + color: rgb(var(--color-gray-500)); + background: rgb(var(--color-gray-100) / 0.5); + padding: 0.125rem 0.375rem; + border-radius: 9999px; +} +.dark #sourcey .json-property-enum-item, +.dark #sourcey .json-property-default-value, +.dark #sourcey .json-property-range { + background: rgb(var(--color-surface-dark-tint) / 0.05); + color: rgb(var(--color-gray-400)); +} + +#sourcey .json-property-enum-item { color: rgb(var(--color-gray-700)); } +.dark #sourcey .json-property-enum-item { color: rgb(var(--color-gray-300)); } + +#sourcey .json-property-default-value::before { + content: '= '; + color: rgb(var(--color-gray-400)); +} + +/* ── Parameter/Schema List (used by SchemaView.tsx, Parameters.tsx) ── */ + +#sourcey .param-item { + padding: 1rem 0; + border-bottom: 1px solid rgb(var(--color-gray-100)); +} +.dark #sourcey .param-item { + border-bottom-color: rgb(var(--color-gray-800)); +} + +#sourcey .param-item:last-child { + border-bottom: none; +} + +#sourcey .param-header { + display: flex; + align-items: baseline; + gap: 0.5rem; + flex-wrap: wrap; +} + +#sourcey .param-name { + font-family: var(--font-mono); + font-size: 0.875rem; + font-weight: 600; + color: rgb(var(--color-primary-ink)); + background: transparent; + border: none; + padding: 0; +} +.dark #sourcey .param-name { + color: rgb(var(--color-primary-light)); +} + +#sourcey .param-type { + display: inline-flex; + align-items: baseline; + gap: 0.375rem; +} + +#sourcey .param-in { + display: inline-flex; + align-items: center; + padding: 0.125rem 0.5rem; + font-size: 0.75rem; + font-weight: 500; + border-radius: 0.375rem; + background: rgb(var(--color-gray-100) / 0.5); + color: rgb(var(--color-gray-600)); + margin-left: auto; +} +.dark #sourcey .param-in { + background: rgb(var(--color-surface-dark-tint) / 0.05); + color: rgb(var(--color-gray-200)); +} + +#sourcey .param-description { + padding-top: 0.5rem; + font-size: 0.875rem; + color: rgb(var(--color-gray-700)); +} +.dark #sourcey .param-description { + color: rgb(var(--color-gray-400)); +} + + +/* ── Steps (numbered step list with vertical connector) ────────────── */ + +#sourcey .steps { + margin-left: 0.875rem; + margin-top: 1rem; + margin-bottom: 1.5rem; +} + +#sourcey .steps .step-item { + position: relative; + display: flex; + align-items: flex-start; + padding-bottom: 1.25rem; +} + +#sourcey .steps .step-item::before { + content: ''; + position: absolute; + left: 13px; + top: 2.75rem; + bottom: 0; + width: 1px; + background: rgb(var(--color-gray-200) / 0.7); +} +.dark #sourcey .steps .step-item::before { + background: rgb(255 255 255 / 0.1); +} + +#sourcey .steps .step-item:last-child::before { + background: linear-gradient(to bottom, rgb(var(--color-gray-200) / 0.7), transparent); +} +.dark #sourcey .steps .step-item:last-child::before { + background: linear-gradient(to bottom, rgb(255 255 255 / 0.1), transparent); +} + +#sourcey .steps .step-number { + position: relative; + display: flex; + align-items: center; + justify-content: center; + width: 1.75rem; + height: 1.75rem; + flex-shrink: 0; + border-radius: 9999px; + background: rgb(var(--color-gray-50)); + font-size: 0.75rem; + font-weight: 600; + color: rgb(var(--color-gray-900)); + margin-top: 0.5rem; +} +.dark #sourcey .steps .step-number { + background: rgb(255 255 255 / 0.1); + color: rgb(var(--color-gray-50)); +} + +#sourcey .steps .step-body { + padding-left: 1rem; + flex: 1; + overflow: hidden; +} + +#sourcey .steps .step-title { + margin-top: 0.5rem; + font-weight: 600; + color: rgb(var(--color-gray-900)); +} +.dark #sourcey .steps .step-title { + color: rgb(var(--color-gray-200)); +} + +#sourcey .steps .step-content { + margin-top: 0.25rem; +} + +#sourcey .steps .step-content p { + margin: 0.25rem 0; +} + +/* ── Card Group (icon cards in a grid) ─────────────────────────────── */ + +#sourcey .card-group { + display: grid; + gap: 1rem; + margin-top: 1.25rem; + margin-bottom: 2rem; +} +@media (min-width: 640px) { + #sourcey .card-group[data-cols="2"] { grid-template-columns: repeat(2, 1fr); } + #sourcey .card-group[data-cols="3"] { grid-template-columns: repeat(3, 1fr); } + #sourcey .card-group[data-cols="4"] { grid-template-columns: repeat(4, 1fr); } +} + +#sourcey .card-item { + display: block; + position: relative; + border: 1px solid rgb(var(--color-gray-950) / 0.1); + border-radius: var(--radius); + padding: 1.25rem 1.5rem; + background: rgb(var(--color-background-light)); + text-decoration: none; + color: inherit; + cursor: pointer; + overflow: hidden; + transition: border-color 0.15s; +} +.dark #sourcey .card-item { + border-color: rgb(255 255 255 / 0.1); + background: rgb(var(--color-background-dark)); +} + +#sourcey .card-item:hover { + border-color: rgb(var(--color-primary)); +} +.dark #sourcey .card-item:hover { + border-color: rgb(var(--color-primary-light)); +} + +#sourcey .card-icon { + width: 1.5rem; + height: 1.5rem; + flex-shrink: 0; + color: rgb(var(--color-primary)); + margin-bottom: 0.75rem; +} +.dark #sourcey .card-icon { + color: rgb(var(--color-primary-light)); +} + +#sourcey .card-item-title { + font-size: 1rem; + font-weight: 600; + color: rgb(var(--color-gray-800)); + margin: 0 0 0.25rem; +} +.dark #sourcey .card-item-title { + color: #fff; +} + +#sourcey .card-item-content { + margin-top: 0.25rem; + font-size: 1rem; + line-height: 1.5; + color: rgb(var(--color-gray-600)); +} +.dark #sourcey .card-item-content { + color: rgb(var(--color-gray-400)); +} + +#sourcey .card-item-content p { + margin: 0; +} + +/* ── Accordion (expandable details) ────────────────────────────────── */ + +#sourcey .accordion-group { + margin-top: 0; + margin-bottom: 0.75rem; + border-radius: var(--radius); + border: 1px solid rgb(var(--color-gray-200) / 0.7); + overflow: hidden; +} +.dark #sourcey .accordion-group { + border-color: rgb(var(--color-gray-800) / 0.5); +} + +#sourcey .accordion-item { + border-bottom: 1px solid rgb(var(--color-gray-200) / 0.7); + background: rgb(var(--color-background-light)); +} +.dark #sourcey .accordion-item { + border-bottom-color: rgb(var(--color-gray-800) / 0.5); + background: rgb(var(--color-code-block-dark)); +} + +#sourcey .accordion-item:last-child { + border-bottom: none; +} + +#sourcey .accordion-trigger { + display: flex; + align-items: center; + gap: 0.5rem; + width: 100%; + padding: 1rem 1.25rem; + cursor: pointer; + font-weight: 500; + color: rgb(var(--color-gray-900)); + list-style: none; +} +#sourcey .accordion-trigger::-webkit-details-marker { display: none; } +.dark #sourcey .accordion-trigger { + color: rgb(var(--color-gray-200)); +} + +#sourcey .accordion-trigger:hover { + background: rgb(var(--color-gray-100)); +} +.dark #sourcey .accordion-trigger:hover { + background: rgb(var(--color-gray-800)); +} + +#sourcey .accordion-trigger::before { + content: ''; + display: inline-block; + width: 0.75rem; + height: 0.75rem; + flex-shrink: 0; + background: rgb(var(--color-gray-700)); + mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 256 512'%3E%3Cpath d='M246.6 278.6c12.5-12.5 12.5-32.8 0-45.3l-128-128c-9.2-9.2-22.9-11.9-34.9-6.9s-19.8 16.6-19.8 29.6l0 256c0 12.9 7.8 24.6 19.8 29.6s25.7 2.2 34.9-6.9l128-128z'/%3E%3C/svg%3E"); + mask-repeat: no-repeat; + mask-position: center; + mask-size: contain; + transition: transform 0.15s; +} +.dark #sourcey .accordion-trigger::before { + background: rgb(var(--color-gray-400)); +} + +#sourcey .accordion-item[open] > .accordion-trigger::before { + transform: rotate(90deg); +} + +#sourcey .accordion-content { + padding: 0 1.25rem 1rem 2.5rem; + color: rgb(var(--color-gray-700)); +} +.dark #sourcey .accordion-content { + color: rgb(var(--color-gray-400)); +} + +#sourcey .accordion-content p { + margin: 0.25rem 0; +} + +/* ── Callouts (:::note, :::warning, :::tip, :::info) ───────────────── */ + +#sourcey .callout { + margin: 1.25rem 0; + border: none; + border-left: 2px solid; + border-radius: 0; + padding: 0.875rem 1rem; + font-size: 0.875rem; + line-height: 1.6; + color: rgb(var(--color-gray-700)); + border-left-color: rgb(var(--color-gray-300)); +} +.dark #sourcey .callout { + border-left-color: rgb(var(--color-gray-700)); + color: rgb(var(--color-gray-400)); +} + +#sourcey .callout-title { + font-weight: 600; + font-size: 0.8125rem; + text-transform: uppercase; + letter-spacing: 0.04em; +} + +/* Remove bottom margin when no content follows */ +#sourcey .callout-title:last-child { + margin-bottom: 0; +} + +#sourcey .callout-content { + margin-top: 0.375rem; +} + +#sourcey .callout-content p { + margin: 0.25rem 0; +} + +#sourcey .callout-content p:last-child { + margin-bottom: 0; +} + +/* Note — blue */ +#sourcey .callout-note { border-left-color: #3b82f6; } +.dark #sourcey .callout-note { border-left-color: #60a5fa; } +#sourcey .callout-note .callout-title { color: #3b82f6; } +.dark #sourcey .callout-note .callout-title { color: #60a5fa; } + +/* Warning — amber */ +#sourcey .callout-warning { border-left-color: #f59e0b; } +.dark #sourcey .callout-warning { border-left-color: #fbbf24; } +#sourcey .callout-warning .callout-title { color: #f59e0b; } +.dark #sourcey .callout-warning .callout-title { color: #fbbf24; } + +/* ── Changelog ───────────────────────────────────────────────────── */ + +#sourcey .sourcey-changelog-page { + width: 100%; +} + +#sourcey .sourcey-changelog-header { + margin-bottom: 2rem; +} + +#sourcey .sourcey-changelog-description { + margin-top: 0.75rem; + font-size: 1.05rem; + line-height: 1.7; + color: rgb(var(--color-gray-600)); + max-width: 65ch; + text-wrap: pretty; +} + +.dark #sourcey .sourcey-changelog-description { + color: rgb(var(--color-gray-400)); +} + +#sourcey .sourcey-changelog-description a { + color: rgb(var(--color-primary-ink)); + text-decoration: none; + border-bottom: 1px solid rgb(var(--color-primary-ink) / 0.3); +} + +#sourcey .sourcey-changelog-description a:hover { + border-bottom-color: rgb(var(--color-primary-ink)); +} + +.dark #sourcey .sourcey-changelog-description a { + color: rgb(var(--color-primary-light)); + border-bottom-color: rgb(var(--color-primary-light) / 0.3); +} + +.dark #sourcey .sourcey-changelog-description a:hover { + border-bottom-color: rgb(var(--color-primary-light)); +} + +#sourcey .sourcey-changelog-description code { + font-size: 0.92em; + padding: 0.05rem 0.3rem; + border-radius: 0.25rem; + background: rgb(var(--color-gray-100)); + color: rgb(var(--color-gray-800)); +} + +.dark #sourcey .sourcey-changelog-description code { + background: rgb(255 255 255 / 0.08); + color: rgb(var(--color-gray-200)); +} + +#sourcey .sourcey-changelog-list { + display: flex; + flex-direction: column; + gap: 1rem; +} + +#sourcey .sourcey-changelog-version { + border: 1px solid rgb(var(--color-gray-200) / 0.8); + border-radius: 1rem; + padding: 1.25rem 1.25rem 1rem; + background: linear-gradient(180deg, rgb(var(--color-gray-50) / 0.75), rgb(255 255 255)); +} + +.dark #sourcey .sourcey-changelog-version { + border-color: rgb(var(--color-gray-800) / 0.8); + background: linear-gradient(180deg, rgb(255 255 255 / 0.03), rgb(255 255 255 / 0.015)); +} + +#sourcey .sourcey-changelog-version-unreleased { + border-color: rgb(var(--color-primary) / 0.18); + border-left: 3px solid rgb(var(--color-primary)); + padding-left: calc(1.25rem - 2px); + background: linear-gradient(180deg, rgb(var(--color-primary) / 0.04), rgb(var(--color-primary) / 0.015)); +} + +.dark #sourcey .sourcey-changelog-version-unreleased { + border-color: rgb(var(--color-primary-light) / 0.22); + border-left-color: rgb(var(--color-primary-light)); + background: linear-gradient(180deg, rgb(var(--color-primary-light) / 0.06), rgb(var(--color-primary-light) / 0.02)); +} + +#sourcey .sourcey-changelog-version-header { + display: flex; + align-items: flex-start; + justify-content: space-between; + gap: 1rem; + margin-bottom: 1rem; +} + +@media (max-width: 768px) { + #sourcey .sourcey-changelog-version-header { + flex-direction: column; + } +} + +#sourcey .sourcey-changelog-version-heading { + display: flex; + align-items: center; + gap: 0.5rem; + flex-wrap: wrap; +} + +#sourcey .sourcey-changelog-version-link { + font-size: 1.25rem; + font-weight: 700; + color: rgb(var(--color-gray-900)); + text-decoration: none; +} + +.dark #sourcey .sourcey-changelog-version-link { + color: rgb(var(--color-gray-200)); +} + +#sourcey .sourcey-changelog-version-link:hover { + color: rgb(var(--color-primary-ink)); +} + +.dark #sourcey .sourcey-changelog-version-link:hover { + color: rgb(var(--color-primary-light)); +} + +#sourcey .sourcey-changelog-version-meta { + display: flex; + align-items: center; + gap: 0.75rem; + font-size: 0.925rem; + color: rgb(var(--color-gray-500)); +} + +.dark #sourcey .sourcey-changelog-version-meta { + color: rgb(var(--color-gray-400)); +} + +#sourcey .sourcey-changelog-compare-link { + color: rgb(var(--color-primary-ink)); + text-decoration: none; +} + +.dark #sourcey .sourcey-changelog-compare-link { + color: rgb(var(--color-primary-light)); +} + +#sourcey .sourcey-changelog-pill { + display: inline-flex; + align-items: center; + border-radius: 999px; + padding: 0.15rem 0.5rem; + font-size: 0.72rem; + font-weight: 700; + letter-spacing: 0.03em; +} + +#sourcey .sourcey-changelog-pill-yanked { + background: rgb(239 68 68 / 0.12); + color: rgb(185 28 28); +} + +.dark #sourcey .sourcey-changelog-pill-yanked { + background: rgb(248 113 113 / 0.15); + color: rgb(252 165 165); +} + +#sourcey .sourcey-changelog-pill-pre { + background: rgb(var(--color-gray-100)); + color: rgb(var(--color-gray-600)); +} + +.dark #sourcey .sourcey-changelog-pill-pre { + background: rgb(255 255 255 / 0.08); + color: rgb(var(--color-gray-300)); +} + +#sourcey .sourcey-changelog-pill-next { + background: rgb(var(--color-primary) / 0.1); + color: rgb(var(--color-primary-ink)); + text-transform: uppercase; + letter-spacing: 0.06em; + font-size: 0.68rem; +} + +.dark #sourcey .sourcey-changelog-pill-next { + background: rgb(var(--color-primary-light) / 0.14); + color: rgb(var(--color-primary-light)); +} + +#sourcey .sourcey-changelog-summary { + margin-bottom: 1rem; +} + +#sourcey .sourcey-changelog-summary p:first-child { + margin-top: 0; +} + +#sourcey .sourcey-changelog-sections { + display: flex; + flex-direction: column; + gap: 0.875rem; +} + +#sourcey .sourcey-changelog-section { + display: flex; + flex-direction: column; + gap: 0.5rem; +} + +#sourcey .sourcey-changelog-section-header { + display: flex; + align-items: center; + gap: 0.5rem; +} + +#sourcey .sourcey-changelog-entry-list { + margin: 0; + padding-left: 1.25rem; + color: rgb(var(--color-gray-700)); +} + +.dark #sourcey .sourcey-changelog-entry-list { + color: rgb(var(--color-gray-300)); +} + +#sourcey .sourcey-changelog-entry-list li { + margin: 0.35rem 0; +} + +#sourcey .sourcey-changelog-entry-list li > p { + margin: 0; +} + +#sourcey .sourcey-changelog-badge { + text-transform: none; +} + +#sourcey .sourcey-changelog-badge-added { + background: rgb(var(--color-success) / 0.12); + color: rgb(21 128 61); +} + +.dark #sourcey .sourcey-changelog-badge-added { + background: rgb(var(--color-success) / 0.16); + color: rgb(134 239 172); +} + +#sourcey .sourcey-changelog-badge-changed { + background: rgb(var(--color-primary) / 0.12); + color: rgb(var(--color-primary-ink)); +} + +.dark #sourcey .sourcey-changelog-badge-changed { + background: rgb(var(--color-primary-light) / 0.12); + color: rgb(var(--color-primary-light)); +} + +#sourcey .sourcey-changelog-badge-fixed { + background: rgb(245 158 11 / 0.14); + color: rgb(180 83 9); +} + +.dark #sourcey .sourcey-changelog-badge-fixed { + background: rgb(251 191 36 / 0.16); + color: rgb(253 224 71); +} + +#sourcey .sourcey-changelog-badge-removed, +#sourcey .sourcey-changelog-badge-security { + background: rgb(239 68 68 / 0.12); + color: rgb(185 28 28); +} + +.dark #sourcey .sourcey-changelog-badge-removed, +.dark #sourcey .sourcey-changelog-badge-security { + background: rgb(248 113 113 / 0.16); + color: rgb(252 165 165); +} + +#sourcey .sourcey-changelog-badge-deprecated, +#sourcey .sourcey-changelog-badge-other { + background: rgb(var(--color-gray-100)); + color: rgb(var(--color-gray-600)); +} + +.dark #sourcey .sourcey-changelog-badge-deprecated, +.dark #sourcey .sourcey-changelog-badge-other { + background: rgb(255 255 255 / 0.08); + color: rgb(var(--color-gray-300)); +} + +/* Tip — green */ +#sourcey .callout-tip { border-left-color: #22c55e; } +.dark #sourcey .callout-tip { border-left-color: #4ade80; } +#sourcey .callout-tip .callout-title { color: #22c55e; } +.dark #sourcey .callout-tip .callout-title { color: #4ade80; } + +/* Info — violet */ +#sourcey .callout-info { border-left-color: #8b5cf6; } +.dark #sourcey .callout-info { border-left-color: #a78bfa; } +#sourcey .callout-info .callout-title { color: #8b5cf6; } +.dark #sourcey .callout-info .callout-title { color: #a78bfa; } + +/* ── Directive Tabs (:::tabs, :::code-group) ───────────────────────── */ + +#sourcey .directive-tabs { + margin: 1.25rem 0; + border: 1px solid rgb(var(--color-stone-950) / 0.1); + border-radius: var(--radius); + overflow: hidden; +} +.dark #sourcey .directive-tabs { + border-color: rgb(255 255 255 / 0.1); +} + +#sourcey .directive-tab-bar { + display: flex; + gap: 0; + border-bottom: 1px solid rgb(var(--color-stone-200)); + background: rgb(var(--color-stone-50)); + padding: 0 0.25rem; +} +.dark #sourcey .directive-tab-bar { + border-bottom-color: rgb(255 255 255 / 0.06); + background: rgb(var(--color-code-block-dark)); +} + +#sourcey .directive-tab { + position: relative; + padding: 0.625rem 1rem; + font-size: 0.8125rem; + font-weight: 500; + color: rgb(var(--color-stone-500)); + background: transparent; + border: none; + cursor: pointer; + transition: color 0.15s; +} +#sourcey .directive-tab:hover { + color: rgb(var(--color-gray-900)); +} +.dark #sourcey .directive-tab:hover { + color: rgb(var(--color-gray-300)); +} + +#sourcey .directive-tab.active { + color: rgb(var(--color-primary-ink)); +} +.dark #sourcey .directive-tab.active { + color: rgb(var(--color-primary-light)); +} + +#sourcey .directive-tab.active::after { + content: ''; + position: absolute; + right: 0.5rem; + bottom: -1px; + left: 0.5rem; + height: 2px; + border-radius: 9999px; + background: rgb(var(--color-primary)); +} +.dark #sourcey .directive-tab.active::after { + background: rgb(var(--color-primary-light)); +} + +#sourcey .directive-tab-panel { + display: none; + padding: 1rem 1.25rem; +} + +#sourcey .directive-tab-panel.active { + display: block; +} + +/* Code group: tighter padding, code blocks fill the panel */ +#sourcey .directive-code-group .directive-tab-panel { + padding: 0; +} + +#sourcey .directive-code-group .directive-tab-panel pre { + margin: 0; + border-radius: 0; +} + +/* Strip nested code block chrome inside tab panels */ +#sourcey .directive-tabs .prose-code-block { + border: none; + border-radius: 0; + margin: 0; +} + +#sourcey .directive-tabs .prose-code-block .prose-code-copy { + display: none; +} + +/* ── Mobile navigation drawer (dialog) ────────────────────────────── */ + +.mobile-nav-dialog { + padding: 0; + border: none; + max-width: 20rem; + width: 80%; + height: 100%; + max-height: 100%; + margin: 0; + overflow-y: auto; + font-family: var(--font-sans); + font-size: 0.875rem; + line-height: 1.5rem; + background: rgb(var(--color-background-light)); + color: rgb(var(--color-gray-500)); +} +.mobile-nav-dialog[open] { + display: flex; + flex-direction: column; +} +.dark .mobile-nav-dialog { + background: rgb(var(--color-background-dark)); + color: rgb(var(--color-gray-400)); +} +.mobile-nav-dialog::backdrop { + background: rgb(0 0 0 / 0.25); + backdrop-filter: blur(2px); +} +.mobile-nav-dialog[open] { + animation: drawer-slide-in 0.2s ease-out; +} +.mobile-nav-dialog[open]::backdrop { + animation: drawer-fade-in 0.2s ease-out; +} + +/* ── Drawer group dropdown ─────────────────────────────────────────── */ + +.drawer-dropdown { + position: relative; +} + +.drawer-dropdown-trigger { + position: relative; + z-index: 11; + display: flex; + align-items: center; + justify-content: space-between; + gap: 0.5rem; + width: 100%; + padding: 0.625rem 1.125rem; + border-radius: var(--radius, 0.5rem); + font-size: 1rem; + font-weight: 600; + font-family: var(--font-sans); + color: rgb(var(--color-gray-900)); + background: rgb(var(--color-background-light)); + border: none; + box-shadow: inset 0 0 0 1px rgb(var(--color-gray-200)); + cursor: pointer; + text-align: left; +} +.dark .drawer-dropdown-trigger { + color: rgb(var(--color-gray-200)); + background: rgb(var(--color-background-dark)); + box-shadow: inset 0 0 0 1px rgb(var(--color-gray-600)); +} +.drawer-dropdown-trigger[aria-expanded="true"] { + border-bottom-left-radius: 0; + border-bottom-right-radius: 0; + box-shadow: inset 1px 0 0 rgb(var(--color-gray-200)), inset -1px 0 0 rgb(var(--color-gray-200)), inset 0 1px 0 rgb(var(--color-gray-200)); +} +.dark .drawer-dropdown-trigger[aria-expanded="true"] { + box-shadow: inset 1px 0 0 rgb(var(--color-gray-600)), inset -1px 0 0 rgb(var(--color-gray-600)), inset 0 1px 0 rgb(var(--color-gray-600)); +} + +.drawer-dropdown-chevron { + color: rgb(var(--color-gray-400)); + transition: transform 0.15s ease; + flex-shrink: 0; +} +.drawer-dropdown-trigger[aria-expanded="true"] .drawer-dropdown-chevron { + transform: rotate(180deg); +} + +.drawer-dropdown-list { + position: absolute; + top: 100%; + left: 0; + right: 0; + z-index: 10; + list-style: none; + margin: 0; + padding: 0.375rem 0; + border-radius: 0 0 var(--radius, 0.5rem) var(--radius, 0.5rem); + background: rgb(var(--color-background-light)); + border: none; + box-shadow: inset 1px 0 0 rgb(var(--color-gray-200)), inset -1px 0 0 rgb(var(--color-gray-200)), inset 0 -1px 0 rgb(var(--color-gray-200)), 0 6px 16px rgb(0 0 0 / 0.08); +} +.dark .drawer-dropdown-list { + background: rgb(var(--color-background-dark)); + box-shadow: inset 1px 0 0 rgb(var(--color-gray-600)), inset -1px 0 0 rgb(var(--color-gray-600)), inset 0 -1px 0 rgb(var(--color-gray-600)), 0 6px 16px rgb(0 0 0 / 0.3); +} + +.drawer-dropdown-item { + display: block; + width: 100%; + padding: 0.5rem 1.125rem; + font-size: 1rem; + font-family: var(--font-sans); + text-align: left; + color: rgb(var(--color-gray-600)); + background: none; + border: none; + cursor: pointer; +} +.drawer-dropdown-item:hover { + background: rgb(var(--color-gray-50)); +} +.dark .drawer-dropdown-item { + color: rgb(var(--color-gray-400)); +} +.dark .drawer-dropdown-item:hover { + background: rgb(var(--color-gray-800)); +} +.drawer-dropdown-item.active { + color: rgb(var(--color-primary-ink)); + font-weight: 500; +} +.dark .drawer-dropdown-item.active { + color: rgb(var(--color-primary-light)); +} + +/* Drawer nav items — larger touch targets */ +#sourcey .mobile-nav-dialog .nav-link, +#sourcey .mobile-nav-dialog .nav-link:hover, +#sourcey .mobile-nav-dialog .nav-link.active { + padding-top: 0.5rem; + padding-bottom: 0.5rem; +} +.mobile-nav-dialog ul { + display: flex; + flex-direction: column; + gap: 0.125rem; +} + +@keyframes drawer-slide-in { + from { transform: translateX(-100%); } + to { transform: translateX(0); } +} +@keyframes drawer-fade-in { + from { opacity: 0; } + to { opacity: 1; } +} + +/* ── Code group cards (API right-hand panels) ─────────────────────── */ + +#sourcey .code-group { + position: relative; + display: flex; + flex-direction: column; + /* Visible so an open header dropdown menu is not clipped by the card; the + code body's rounded corners are clipped by .code-card-body instead. */ + overflow: visible; + border-radius: var(--radius); + border: 1px solid rgb(var(--color-stone-950) / 0.1); +} +.dark #sourcey .code-group { + border-color: rgb(255 255 255 / 0.1); +} + +#sourcey .code-group > div:first-child { + background: rgb(var(--color-stone-50)); + border-top-left-radius: var(--radius); + border-top-right-radius: var(--radius); +} +.dark #sourcey .code-group > div:first-child { + background: rgb(255 255 255 / 0.03); +} + +/* Clips the code panels' rounded bottom corners now that the card itself does + not clip. Horizontal code scrolling stays on the inner body element. */ +#sourcey .code-card-body { + overflow: hidden; + border-bottom-left-radius: var(--radius); + border-bottom-right-radius: var(--radius); +} + +/* ── Selection ─────────────────────────────────────────────────────── */ + +#sourcey ::selection { background: rgb(var(--color-primary) / 0.12); } + +/* ── Search Dialog ────────────────────────────────────────────────── */ + +#sourcey #search-dialog { + display: none; + position: fixed; + inset: 0; + z-index: 500; + background: transparent; +} + +#sourcey #search-dialog.open { + display: block; +} + +#sourcey .search-dialog-inner { + position: absolute; + background: rgb(var(--color-background-light)); + border-radius: var(--radius); + border: 1px solid rgb(var(--color-gray-200) / 0.7); + box-shadow: 0 8px 32px rgb(var(--color-overlay) / 0.12); + overflow: hidden; +} +.dark #sourcey .search-dialog-inner { + background: rgb(var(--color-gray-900)); + border-color: rgb(var(--color-gray-700) / 0.5); + box-shadow: 0 8px 32px rgb(var(--color-overlay) / 0.4); +} + +#sourcey .search-input-row { + display: flex; + align-items: center; + gap: 0.625rem; + padding: 0.75rem 1rem; + border-bottom: 1px solid rgb(var(--color-gray-200)); +} +.dark #sourcey .search-input-row { + border-bottom-color: rgb(var(--color-gray-800)); +} + +#sourcey .search-input-icon { + width: 1.125rem; + height: 1.125rem; + flex-shrink: 0; + color: rgb(var(--color-gray-400)); +} + +#sourcey #search-input { + width: 100%; + border: none; + font-family: var(--font-sans); + font-size: 0.9375rem; + color: rgb(var(--color-gray-900)); + background: transparent; + outline: none; +} +.dark #sourcey #search-input { + color: rgb(var(--color-gray-100)); +} + +#sourcey #search-input::placeholder { color: rgb(var(--color-gray-400)); } + +#sourcey #search-results { + max-height: 50vh; + overflow-y: auto; + padding: 0.25rem; +} + +#sourcey .search-category { + padding: 0.5rem 0.75rem 0.25rem; + font-size: 0.6875rem; + font-weight: 600; + text-transform: uppercase; + letter-spacing: 0.05em; + color: rgb(var(--color-gray-400)); +} + +#sourcey .search-footer { + display: flex; + align-items: center; + gap: 1rem; + padding: 0.5rem 0.75rem; + border-top: 1px solid rgb(var(--color-gray-200)); + font-size: 0.6875rem; + color: rgb(var(--color-gray-400)); +} +.dark #sourcey .search-footer { + border-top-color: rgb(var(--color-gray-800)); +} + +#sourcey .search-footer-hint { + display: flex; + align-items: center; + gap: 0.25rem; +} + +#sourcey .search-footer kbd, +#sourcey #search-open kbd { + display: inline-flex; + align-items: center; + justify-content: center; + min-width: 1.25rem; + height: 1.125rem; + padding: 0 0.25rem; + font-family: var(--font-sans); + font-size: 0.625rem; + font-weight: 500; + border-radius: 0.25rem; + border: 1px solid rgb(var(--color-gray-200)); + background: rgb(var(--color-gray-50)); + color: rgb(var(--color-gray-500)); +} +.dark #sourcey .search-footer kbd, +.dark #sourcey #search-open kbd { + border-color: rgb(var(--color-gray-700)); + background: rgb(var(--color-gray-800)); + color: rgb(var(--color-gray-400)); +} + +#sourcey .search-result { + display: flex; + align-items: baseline; + gap: 0.5rem; + padding: 0.5rem 0.75rem; + text-decoration: none; + color: rgb(var(--color-gray-700)); + border-radius: 0.375rem; + cursor: pointer; + transition: background 0.1s; +} +.dark #sourcey .search-result { + color: rgb(var(--color-gray-400)); +} + +#sourcey .search-result:hover, +#sourcey .search-result.active { + background: rgb(var(--color-primary) / 0.06); + color: rgb(var(--color-gray-900)); +} +.dark #sourcey .search-result:hover, +.dark #sourcey .search-result.active { + background: rgb(var(--color-primary-light) / 0.08); + color: rgb(var(--color-gray-200)); +} + +#sourcey .search-result-main { + display: flex; + align-items: baseline; + gap: 0.375rem; + flex: 1; + min-width: 0; +} + +#sourcey .search-result-method { + display: inline-flex; + align-items: center; + padding: 0.125rem 0.375rem; + font-size: 0.625rem; + font-weight: 700; + line-height: 1; + letter-spacing: 0.04em; + text-transform: uppercase; + white-space: nowrap; + border: 1px solid transparent; + border-radius: 3px; + color: rgb(var(--color-background-light)); + flex-shrink: 0; +} + +#sourcey .search-result-method.method-get { background: var(--method-get); } +#sourcey .search-result-method.method-post { background: var(--method-post); } +#sourcey .search-result-method.method-put { background: var(--method-put); } +#sourcey .search-result-method.method-delete { background: var(--method-delete); } +#sourcey .search-result-method.method-patch { background: var(--method-patch); } +#sourcey .search-result-method.method-tool { background: var(--method-tool); } +#sourcey .search-result-method.method-resource { background: var(--method-resource); } +#sourcey .search-result-method.method-prompt { background: var(--method-prompt); } + +#sourcey .search-result-path { + font-family: var(--font-mono); + font-size: 0.8125rem; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +#sourcey .search-result-summary { + font-size: 0.8125rem; + color: rgb(var(--color-gray-500)); + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +#sourcey .search-result-tag { + font-size: 0.6875rem; + color: rgb(var(--color-gray-400)); + white-space: nowrap; + flex-shrink: 0; +} + +#sourcey .search-loading { + padding: 1rem; + color: rgb(var(--color-gray-500)); + font-size: 0.8125rem; +} + +/* ── Godoc rendering ─────────────────────────────────────────────── */ + +#sourcey .godoc-import, +#sourcey .godoc-import-path { + font-size: 0.8125rem; + color: rgb(var(--color-gray-500)); + margin: 0.25rem 0 1.5rem; +} + +#sourcey .godoc-import code, +#sourcey .godoc-import-path code { + font-family: var(--font-mono); + background: rgba(var(--color-gray-100), 0.6); + padding: 0.125rem 0.375rem; + border-radius: 3px; +} + +#sourcey .godoc-source { + margin: -0.25rem 0 0.625rem; + font-size: 0.75rem; + color: rgb(var(--color-gray-500)); +} + +#sourcey .godoc-source a { + color: inherit; + text-decoration: none; +} + +#sourcey .godoc-source a:hover { + color: rgb(var(--color-primary-ink)); +} + +#sourcey .godoc-toc { + margin: 1.5rem 0 2.5rem; + padding: 0.875rem 1rem; + border: 1px solid rgb(var(--color-gray-200)); + border-radius: 6px; + background: rgba(var(--color-gray-50), 0.5); +} + +#sourcey .godoc-toc h4 { + margin: 0 0 0.5rem; + font-size: 0.6875rem; + font-weight: 700; + text-transform: uppercase; + letter-spacing: 0.04em; + color: rgb(var(--color-gray-500)); +} + +#sourcey .godoc-toc ul { + list-style: none; + margin: 0; + padding: 0; + font-size: 0.8125rem; +} + +#sourcey .godoc-toc li { + margin: 0.125rem 0; +} + +#sourcey .godoc-toc li.godoc-toc-sub { + padding-left: 1rem; + font-family: var(--font-mono); + font-size: 0.75rem; + color: rgb(var(--color-gray-600)); +} + +#sourcey .godoc-toc a { + color: inherit; + text-decoration: none; + border-bottom: 1px dotted transparent; +} + +#sourcey .godoc-toc a:hover { + color: rgb(var(--color-primary)); + border-bottom-color: currentColor; +} + +#sourcey .godoc-symbol { + font-family: var(--font-mono); + font-size: 0.95rem; + font-weight: 600; + margin: 1.75rem 0 0.5rem; + color: rgb(var(--color-gray-900)); + scroll-margin-top: 5rem; +} + +#sourcey .godoc-doc { + margin: 0.5rem 0 0.75rem; + color: rgb(var(--color-gray-700)); + font-size: 0.9375rem; + line-height: 1.65; +} + +#sourcey .godoc-doc p:first-child { + margin-top: 0; +} + +#sourcey .godoc-doc p:last-child { + margin-bottom: 0; +} + +#sourcey .godoc-value, +#sourcey .godoc-func, +#sourcey .godoc-type { + margin: 1rem 0 1.5rem; + scroll-margin-top: 5rem; +} + +#sourcey .godoc-type { + border-top: 1px solid rgb(var(--color-gray-200)); + padding-top: 1.25rem; + margin-top: 2rem; +} + +#sourcey .godoc-anchor { + display: block; + height: 0; + scroll-margin-top: 5rem; +} + +#sourcey .godoc-fields { + margin: 0.75rem 0 1rem; + padding: 0; + border: 1px solid rgb(var(--color-gray-200)); + border-radius: 6px; + background: rgba(var(--color-gray-50), 0.4); +} + +#sourcey .godoc-fields > summary { + cursor: pointer; + padding: 0.5rem 0.875rem; + font-size: 0.75rem; + font-weight: 600; + text-transform: uppercase; + letter-spacing: 0.04em; + color: rgb(var(--color-gray-600)); + list-style: none; +} + +#sourcey .godoc-fields > summary::-webkit-details-marker { + display: none; +} + +#sourcey .godoc-fields > ul { + list-style: none; + margin: 0; + padding: 0; + border-top: 1px solid rgb(var(--color-gray-200)); +} + +#sourcey .godoc-field { + padding: 0.625rem 0.875rem; + border-bottom: 1px solid rgb(var(--color-gray-200)); + font-size: 0.875rem; +} + +#sourcey .godoc-field:last-child { + border-bottom: none; +} + +#sourcey .godoc-field-sig { + font-family: var(--font-mono); + font-size: 0.8125rem; + font-weight: 600; + color: rgb(var(--color-gray-900)); + background: transparent; + padding: 0; +} + +#sourcey .godoc-field-type { + font-weight: 400; + color: rgb(var(--color-gray-700)); +} + +#sourcey .godoc-tag { + font-family: var(--font-mono); + font-size: 0.75rem; + color: rgb(var(--color-gray-500)); + background: transparent; + padding: 0; + margin-left: 0.5rem; +} + +#sourcey .godoc-field-doc { + margin-top: 0.25rem; + font-size: 0.8125rem; + color: rgb(var(--color-gray-600)); + line-height: 1.55; +} + +#sourcey .godoc-example { + margin: 0.75rem 0 1.25rem; + padding: 0; + border: 1px solid rgb(var(--color-gray-200)); + border-radius: 6px; + background: rgba(var(--color-gray-50), 0.4); +} + +#sourcey .godoc-example > summary { + cursor: pointer; + padding: 0.5rem 0.875rem; + font-size: 0.75rem; + font-weight: 600; + text-transform: uppercase; + letter-spacing: 0.04em; + color: rgb(var(--color-gray-600)); + list-style: none; +} + +#sourcey .godoc-example > summary::-webkit-details-marker { + display: none; +} + +#sourcey .godoc-example > summary::before { + content: "▸ "; + color: rgb(var(--color-gray-400)); + margin-right: 0.25rem; +} + +#sourcey .godoc-example[open] > summary::before { + content: "▾ "; +} + +#sourcey .godoc-example > pre, +#sourcey .godoc-example > .godoc-doc, +#sourcey .godoc-example > p { + margin: 0.5rem 0.875rem; +} + +#sourcey .godoc-example-output-label { + margin: 0.5rem 0.875rem 0; + font-size: 0.6875rem; + font-weight: 700; + text-transform: uppercase; + letter-spacing: 0.04em; + color: rgb(var(--color-gray-500)); +} + +#sourcey .godoc-func .godoc-symbol, +#sourcey .godoc-type .godoc-symbol { + word-break: break-word; +} + +/* ── Rust API rendering (rustdoc adapter) ────────────────────────── */ +/* Shared API primitives (api-*) introduced for rustdoc and reusable + by godoc/doxygen in a follow-on retrofit. Class names mirror + rustdoc's DOM so deep-links from a rustdoc URL line up with + sourcey output. */ + +#sourcey .rust-item { + border-top: 1px solid rgb(var(--color-gray-200)); + padding-top: 1rem; + margin-top: 1.25rem; +} +.dark #sourcey .rust-item { + border-top-color: rgb(var(--color-gray-800)); +} + +#sourcey .code-header, +#sourcey .rust-signature { + font-family: ui-monospace, "SF Mono", "Cascadia Code", Consolas, "Liberation Mono", Menlo, monospace; + font-size: 0.9375rem; + color: rgb(var(--color-gray-900)); + white-space: pre-wrap; + word-break: break-word; +} +.dark #sourcey .code-header, +.dark #sourcey .rust-signature { + color: rgb(var(--color-gray-100)); +} + +#sourcey .rust-signature .kw { + color: rgb(var(--color-rose-600)); + font-weight: 600; +} +.dark #sourcey .rust-signature .kw { + color: rgb(var(--color-rose-300)); +} + +#sourcey .rust-signature .ident { + color: rgb(var(--color-indigo-600)); +} +.dark #sourcey .rust-signature .ident { + color: rgb(var(--color-indigo-300)); +} + +#sourcey .rust-signature .lifetime { + color: rgb(var(--color-amber-700)); + font-style: italic; +} +.dark #sourcey .rust-signature .lifetime { + color: rgb(var(--color-amber-300)); +} + +#sourcey .api-rightside, +#sourcey .rightside { + float: right; + font-size: 0.8125rem; + color: rgb(var(--color-gray-500)); +} + +#sourcey .api-since, +#sourcey .since { + font-feature-settings: "tnum"; +} + +#sourcey .api-srclink, +#sourcey .srclink { + color: rgb(var(--color-indigo-600)); + text-decoration: none; +} +#sourcey .api-srclink:hover, +#sourcey .srclink:hover { + text-decoration: underline; +} +.dark #sourcey .api-srclink, +.dark #sourcey .srclink { + color: rgb(var(--color-indigo-300)); +} + +#sourcey .docblock, +#sourcey .rust-doc { + color: rgb(var(--color-gray-700)); + margin-top: 0.5rem; +} +.dark #sourcey .docblock, +.dark #sourcey .rust-doc { + color: rgb(var(--color-gray-300)); +} + +#sourcey .stab, +#sourcey .api-stab { + display: block; + margin: 0.5rem 0; + padding: 0.5rem 0.75rem; + border-radius: 0.375rem; + font-size: 0.875rem; + border: 1px solid transparent; +} +#sourcey .stab.unstable, +#sourcey .api-stab-unstable { + background-color: rgb(var(--color-amber-50)); + border-color: rgb(var(--color-amber-200)); + color: rgb(var(--color-amber-900)); +} +#sourcey .stab.deprecated, +#sourcey .api-stab-deprecated { + background-color: rgb(var(--color-rose-50)); + border-color: rgb(var(--color-rose-200)); + color: rgb(var(--color-rose-900)); +} +#sourcey .stab.portability, +#sourcey .api-stab-portability { + background-color: rgb(var(--color-emerald-50)); + border-color: rgb(var(--color-emerald-200)); + color: rgb(var(--color-emerald-900)); +} +.dark #sourcey .stab.unstable, +.dark #sourcey .api-stab-unstable { + background-color: rgba(251, 191, 36, 0.08); + border-color: rgba(251, 191, 36, 0.25); + color: rgb(var(--color-amber-200)); +} +.dark #sourcey .stab.deprecated, +.dark #sourcey .api-stab-deprecated { + background-color: rgba(244, 63, 94, 0.08); + border-color: rgba(244, 63, 94, 0.25); + color: rgb(var(--color-rose-200)); +} +.dark #sourcey .stab.portability, +.dark #sourcey .api-stab-portability { + background-color: rgba(16, 185, 129, 0.08); + border-color: rgba(16, 185, 129, 0.25); + color: rgb(var(--color-emerald-200)); +} + +/* Collapsible trait-impl block. Chevron pattern mirrors .godoc-example so the + disclosure reads the same across adapters. */ +#sourcey .api-toggle { + margin: 0.75rem 0; + border: 1px solid rgb(var(--color-gray-200)); + border-radius: 6px; + background: rgba(var(--color-gray-50), 0.4); +} +.dark #sourcey .api-toggle { + border-color: rgb(var(--color-gray-800)); +} +#sourcey .api-toggle > summary { + cursor: pointer; + padding: 0.5rem 0.875rem; + list-style: none; + font-family: var(--font-mono); + font-size: 0.8125rem; + color: rgb(var(--color-gray-700)); +} +.dark #sourcey .api-toggle > summary { + color: rgb(var(--color-gray-300)); +} +#sourcey .api-toggle > summary::-webkit-details-marker { + display: none; +} +#sourcey .api-toggle > summary::before { + content: "▸ "; + color: rgb(var(--color-gray-400)); + margin-right: 0.25rem; +} +#sourcey .api-toggle[open] > summary::before { + content: "▾ "; +} +/* The impl header lives inside the summary; keep it inline with the chevron + and strip heading margins. */ +#sourcey .api-toggle > summary .rust-impl-header { + display: inline; + margin: 0; + font-size: inherit; +} +#sourcey .api-toggle-body { + padding: 0.25rem 0.875rem 0.5rem; + border-top: 1px solid rgb(var(--color-gray-200)); +} +.dark #sourcey .api-toggle-body { + border-top-color: rgb(var(--color-gray-800)); +} +/* Marker / auto / blanket trait impls: a quiet list, not expandable boxes. */ +#sourcey .rust-impl-rows { + margin: 0.5rem 0 0.75rem; +} +#sourcey .rust-impl-row { + padding: 0.2rem 0; +} +#sourcey .rust-impl-row .rust-impl-header { + display: inline; + margin: 0; + font-size: 0.8125rem; + font-weight: 400; + color: rgb(var(--color-gray-600)); +} +.dark #sourcey .rust-impl-row .rust-impl-header { + color: rgb(var(--color-gray-400)); +} + +#sourcey .anchor, +#sourcey .api-anchor { + margin-left: 0.4rem; + color: rgb(var(--color-gray-400)); + text-decoration: none; + opacity: 0; + transition: opacity 0.1s ease; +} +#sourcey .section-header:hover .anchor, +#sourcey .section-header:hover .api-anchor, +#sourcey .code-header:hover .anchor, +#sourcey .code-header:hover .api-anchor { + opacity: 1; +} + +/* Inherent-impl methods and trait members render inline as their own sections. + Code (signatures, doctests) flows through the shared Shiki code block, so no + bespoke code styling lives here. */ +#sourcey .rust-member { + margin: 0.75rem 0; +} +#sourcey .rust-method-header { + margin: 0.5rem 0 0.25rem; +} +#sourcey .rust-doctest { + margin: 0.75rem 0; +} + +#sourcey .rust-doctest-badges { + display: flex; + flex-wrap: wrap; + gap: 0.25rem; + margin-bottom: 0.25rem; +} +#sourcey .rust-doctest-badge { + display: inline-block; + padding: 0.05rem 0.4rem; + font-size: 0.6875rem; + font-weight: 600; + border-radius: 0.25rem; + background-color: rgb(var(--color-gray-100)); + color: rgb(var(--color-gray-700)); + text-transform: lowercase; + letter-spacing: 0.02em; +} +.dark #sourcey .rust-doctest-badge { + background-color: rgb(var(--color-gray-800)); + color: rgb(var(--color-gray-300)); +} +#sourcey .rust-doctest-badge-should_panic, +#sourcey .rust-doctest-badge-compile_fail { + background-color: rgb(var(--color-rose-100)); + color: rgb(var(--color-rose-800)); +} +#sourcey .rust-doctest-badge-no_run, +#sourcey .rust-doctest-badge-ignore { + background-color: rgb(var(--color-amber-100)); + color: rgb(var(--color-amber-800)); +} + +#sourcey .rust-doctest-controls { + display: flex; + gap: 0.5rem; + margin-top: 0.5rem; + font-size: 0.8125rem; +} +#sourcey .rust-doctest-run, +#sourcey .rust-doctest-toggle-hidden { + cursor: pointer; + padding: 0.2rem 0.6rem; + border-radius: 0.375rem; + border: 1px solid rgb(var(--color-gray-300)); + background-color: rgb(var(--color-white)); + color: rgb(var(--color-gray-800)); + text-decoration: none; + line-height: 1; +} +#sourcey .rust-doctest-run:hover, +#sourcey .rust-doctest-toggle-hidden:hover { + background-color: rgb(var(--color-gray-50)); +} +.dark #sourcey .rust-doctest-run, +.dark #sourcey .rust-doctest-toggle-hidden { + background-color: rgb(var(--color-gray-900)); + border-color: rgb(var(--color-gray-700)); + color: rgb(var(--color-gray-200)); +} + +/* On the aggregated doctests page the code block already renders as a card, so + the section itself stays borderless. Just space the entries and accent the + heading so they don't read as cards within cards. */ +#sourcey .rust-doctests-index .rust-doctest { + margin: 1.5rem 0; +} +#sourcey .rust-doctests-index .rust-doctest > h3 { + padding-left: 0.625rem; + border-left: 3px solid rgb(var(--color-emerald-500)); +} +.dark #sourcey .rust-doctests-index .rust-doctest > h3 { + border-left-color: rgb(var(--color-emerald-400)); +} diff --git a/docs/sourcey/sourcey.js b/docs/sourcey/sourcey.js new file mode 100644 index 00000000000..53a955649a1 --- /dev/null +++ b/docs/sourcey/sourcey.js @@ -0,0 +1 @@ +(function(){(function(){function e(e){try{return window.sessionStorage.getItem(e)}catch{return null}}function t(e,t){try{window.sessionStorage.setItem(e,t)}catch{}}function n(e){try{window.sessionStorage.removeItem(e)}catch{}}function r(e){var t=(e||`/`).replace(/\/+$/,``)||`/`;return t=t.replace(/\/index(?:\.html)?$/,``)||`/`,t=t.replace(/\.html$/,``),t||`/`}function i(e){if(!e.length)return null;for(var t=e.map(function(e){return r(e).split(`/`).filter(Boolean)}),n=[],i=0;i=document.body.scrollHeight-10){var l=c[c.length-1];i=n.length?l.getAttribute(`data-traverse-target`):l.id}i&&d(i)}}var _=!1;window.addEventListener(`scroll`,function(){_||(_=!0,requestAnimationFrame(function(){g(),_=!1}))},{passive:!0});var v=window.location.hash.slice(1)||new URLSearchParams(window.location.search).get(`target`);v&&document.getElementById(v)?(d(v),requestAnimationFrame(function(){f(v,`instant`)})):g(),window.addEventListener(`hashchange`,function(){var e=window.location.hash.slice(1);e&&(d(e,!0),f(e,`smooth`))})}window.location.hash.slice(1)||new URLSearchParams(window.location.search).get(`target`)?requestAnimationFrame(e):`requestIdleCallback`in window?window.requestIdleCallback(e,{timeout:250}):window.addEventListener(`load`,e,{once:!0})})(),(function(){function e(){var e=null;document.addEventListener(`click`,function(e){var t=e.target.closest(`.code-lang-trigger`);if(document.querySelectorAll(`.code-lang-menu`).forEach(function(e){if(!t||!e.parentElement.contains(t)){e.classList.add(`hidden`);var n=e.parentElement.querySelector(`.code-lang-trigger`);n&&n.setAttribute(`aria-expanded`,`false`)}}),t){e.stopPropagation();var n=t.nextElementSibling;if(n){var r=!n.classList.contains(`hidden`);n.classList.toggle(`hidden`,r),t.setAttribute(`aria-expanded`,r?`false`:`true`)}}}),document.addEventListener(`click`,function(t){var r=t.target.closest(`.code-lang-option`);if(r){var i=r.closest(`.code-lang-dropdown`),a=!!(i&&i.hasAttribute(`data-lang-sync`)),o=r.textContent.trim(),s=r.closest(`.code-lang-menu`);if(s){s.classList.add(`hidden`);var c=s.parentElement.querySelector(`.code-lang-trigger`);c&&c.setAttribute(`aria-expanded`,`false`)}var l=window.scrollY;if(n(r),a&&o!==e){e=o;var u=r.closest(`.code-group`);document.querySelectorAll(`.code-group`).forEach(function(e){e===u||!e.querySelector(`.code-lang-dropdown[data-lang-sync]`)||e.querySelectorAll(`.code-lang-option`).forEach(function(e){e.textContent.trim()===o&&n(e)})})}window.scrollTo(0,l)}});function t(e){var t=e.closest(`[data-response-dropdown]`);if(t){var n=t.getAttribute(`data-response-dropdown`),r=t.closest(`.code-group`),i=r&&r.querySelector(`.response-panel[data-response-panel="`+n+`"]`);if(i)return i}return e.closest(`.code-lang-scope`)||e.closest(`.code-group`)}function n(e){var n=e.closest(`.code-lang-dropdown`),r=t(e),i=e.getAttribute(`data-lang-index`);if(n){var a=n.querySelector(`.code-lang-label`);n.querySelectorAll(`.code-lang-option`).forEach(function(e){var t=e.getAttribute(`data-lang-index`)===i;if(e.setAttribute(`aria-selected`,t?`true`:`false`),e.className=e.className.replace(/(dark:)?text-\[rgb\([^\]]+\)\]/g,``).trim(),t){e.classList.add(`text-[rgb(var(--color-primary))]`,`dark:text-[rgb(var(--color-primary-light))]`),a&&(a.textContent=e.textContent.trim());var r=n.querySelector(`.code-lang-trigger .code-lang-icon`),o=e.querySelector(`.lang-icon`);r&&o&&(r.innerHTML=o.outerHTML)}else e.classList.add(`text-[rgb(var(--color-stone-600))]`,`dark:text-[rgb(var(--color-stone-400))]`)})}r&&r.querySelectorAll(`.code-lang-panel`).forEach(function(e){e.classList.toggle(`active`,e.getAttribute(`data-lang-panel`)===i)})}document.addEventListener(`click`,function(e){var t=e.target.closest(`.response-tab`);if(t){var n=t.closest(`.response-tabs`),r=t.getAttribute(`data-response-index`),i=window.scrollY;n.querySelectorAll(`.response-tab`).forEach(function(e){var t=e.getAttribute(`data-response-index`)===r;e.classList.toggle(`active`,t),e.setAttribute(`aria-selected`,t?`true`:`false`)}),n.querySelectorAll(`.response-panel`).forEach(function(e){e.classList.toggle(`active`,e.getAttribute(`data-response-panel`)===r)}),n.querySelectorAll(`[data-response-dropdown]`).forEach(function(e){e.classList.toggle(`hidden`,e.getAttribute(`data-response-dropdown`)!==r)}),window.scrollTo(0,i)}}),document.addEventListener(`click`,function(e){var t=e.target.closest(`.copy-btn`);if(t){var n=t.closest(`.code-group`)||t.closest(`.prose-code-block`);if(n){var r=n.querySelectorAll(`.code-lang-panel.active, .response-panel.active`),i=r.length?r[r.length-1]:null,a=i?i.querySelector(`code, .code-block, .font-mono`):n.querySelector(`code, .code-block, .font-mono`);if(a){var o=a.textContent||``;navigator.clipboard.writeText(o).then(function(){t.classList.add(`copied`);var e=t.nextElementSibling;e&&e.classList.contains(`copy-tooltip`)&&(e.textContent=`Copied!`),setTimeout(function(){t.classList.remove(`copied`),e&&e.classList.contains(`copy-tooltip`)&&(e.textContent=`Copy`)},2e3)})}}}}),document.addEventListener(`click`,function(e){var t=e.target.closest(`.rust-doctest-toggle-hidden`);if(t){var n=t.getAttribute(`data-target`),r=t.getAttribute(`data-display`),i=n?document.getElementById(n.replace(/^#/,``)):null,a=r?document.getElementById(r.replace(/^#/,``)):null;!i||!a||(i.hasAttribute(`hidden`)?(i.removeAttribute(`hidden`),a.setAttribute(`hidden`,``),t.textContent=`Hide hidden lines`):(i.setAttribute(`hidden`,``),a.removeAttribute(`hidden`),t.textContent=`Show hidden lines`))}}),document.addEventListener(`keydown`,function(e){e.key===`Escape`&&document.querySelectorAll(`.code-lang-menu`).forEach(function(e){e.classList.add(`hidden`);var t=e.parentElement.querySelector(`.code-lang-trigger`);t&&t.setAttribute(`aria-expanded`,`false`)})}),document.addEventListener(`click`,function(e){var t=e.target.closest(`.directive-tab`);if(t){var n=t.getAttribute(`data-tab-group`),r=t.getAttribute(`data-tab-index`),i=window.scrollY;document.querySelectorAll(`.directive-tab[data-tab-group="`+n+`"]`).forEach(function(e){e.classList.toggle(`active`,e.getAttribute(`data-tab-index`)===r)}),document.querySelectorAll(`.directive-tab-panel[data-tab-group="`+n+`"]`).forEach(function(e){e.classList.toggle(`active`,e.getAttribute(`data-tab-index`)===r)}),window.scrollTo(0,i)}})}`requestIdleCallback`in window?window.requestIdleCallback(e,{timeout:250}):window.addEventListener(`load`,e,{once:!0})})(),(function(){var e=`sourcey-theme`,t=document.getElementById(`theme-toggle`),n=document.documentElement;function r(){var t=localStorage.getItem(e);return t===`dark`||t===`light`?t:`light`}function i(e){e===`dark`?n.classList.add(`dark`):n.classList.remove(`dark`),n.style.colorScheme=e,t&&(t.setAttribute(`aria-label`,e===`dark`?`Switch to light mode`:`Switch to dark mode`),t.setAttribute(`title`,e===`dark`?`Light mode`:`Dark mode`))}i(r()),t&&t.addEventListener(`click`,function(){var t=n.classList.contains(`dark`)?`light`:`dark`;localStorage.setItem(e,t),i(t)})})(),(function(){function e(){var e=document.getElementById(`search-dialog`),t=document.getElementById(`search-input`),n=document.getElementById(`search-results`),r=document.getElementById(`search-open`);if(!e||!t||!n)return;var i=[],a=-1,o=[],s=!1,c=document.querySelector(`meta[name="sourcey-search"]`);function l(e){if(s){e();return}if(!c){s=!0,e();return}var t=c.getAttribute(`content`);fetch(t).then(function(e){return e.json()}).then(function(t){i=t.map(function(e){var t=e.title||``,n=e.qualifiedName||``,r=e.owner||``,i=e.tab||``;return{url:e.url,method:e.method||``,path:e.path||``,title:t,summary:n||t,tag:r||i,content:e.content||``,category:e.category||``,featured:!!e.featured,symbolKind:e.symbolKind||``,owner:r,ownerKind:e.ownerKind||``,namespace:e.namespace||``,qualifiedName:n,titleLower:t.toLowerCase(),pathLower:(e.path||``).toLowerCase(),qualifiedLower:n.toLowerCase(),ownerLower:r.toLowerCase(),searchText:[e.method||``,e.path||``,t,n,r,e.ownerKind||``,e.namespace||``,e.symbolKind||``,e.content||``,i].join(` `).toLowerCase()}}),s=!0,e()}).catch(function(){s=!0,e()})}var u=e.querySelector(`.search-dialog-inner`);function d(){if(!(!r||!u)){var e=r.getBoundingClientRect();u.style.position=`absolute`,u.style.top=e.top-4+`px`;var t=Math.min(e.width*.5,200);u.style.left=e.left-t/2+`px`,u.style.width=e.width+t+`px`,u.style.maxWidth=`none`,u.style.transform=`none`,u.style.margin=`0`}}function f(){d(),e.classList.add(`open`),t.value=``,t.focus(),s?m(``):(n.innerHTML=`
    Loading…
    `,l(function(){m(``)})),document.addEventListener(`keydown`,b)}function p(){e.classList.remove(`open`),document.removeEventListener(`keydown`,b)}function m(e){var t=e.toLowerCase().trim();if(t){var n=t.split(/\s+/);o=i.map(function(e){return{entry:e,score:h(e,t,n)}}).filter(function(e){return e.score>0});var r={Pages:0,Endpoints:1,Models:2,Functions:3,Types:4,Enums:5,"Enum Values":6,Variables:7,Friends:8,Properties:9,Members:10,Sections:20};o.sort(function(e,t){return t.score===e.score?(r[e.entry.category]||19)-(r[t.entry.category]||19):t.score-e.score}),o=o.map(function(e){return e.entry}).slice(0,50)}else{var s=i.filter(function(e){return e.featured}),c=i.filter(function(e){return!e.featured&&e.category!==`Sections`});o=s.concat(c).slice(0,30)}a=o.length?0:-1,g()}function h(e,t,n){if(!n.every(function(t){return e.searchText.indexOf(t)!==-1}))return 0;var r=t.replace(/\s+/g,``),i=e.qualifiedLower||``,a=e.titleLower||``,o=e.pathLower||``,s=e.ownerLower||``,c=1;return i&&i===r&&(c+=1200),a&&a===t&&(c+=900),o&&o===t&&(c+=850),i&&i.endsWith(`::`+r)&&(c+=780),s&&r===s+`::`+a&&(c+=760),i&&r.indexOf(`::`)!==-1&&i.indexOf(r)!==-1&&(c+=700),a&&a.indexOf(t)===0&&(c+=500),i&&i.indexOf(r)!==-1&&(c+=420),s&&s.indexOf(r)!==-1&&(c+=240),o&&o.indexOf(t)!==-1&&(c+=180),e.content.toLowerCase().indexOf(t)!==-1&&(c+=80),e.category===`Sections`&&(c-=70),e.symbolKind&&(c+=35),e.featured&&(c+=20),c}function g(){for(var e=``,t=``,r=0;r`+_(s)+``,t=s);var c=`search-result`+(r===a?` active`:``),l=i.method?``+i.method+` `+_(i.path)+``:``+_(i.summary)+``,u=i.tag?``+_(i.tag)+``:``,d=i.method&&i.summary?``+_(i.summary)+``:``;e+=`
    `+l+d+`
    `+u+`
    `}n.innerHTML=e;var f=n.querySelector(`.search-result.active`);f&&f.scrollIntoView({block:`nearest`})}function _(e){var t=document.createElement(`span`);return t.textContent=e,t.innerHTML}function v(e){return _(e).replace(/"/g,`"`).replace(/'/g,`'`)}function y(e){if(!(e<0||e>=o.length)){var t=o[e];p(),window.location.href=t.url}}function b(e){if(e.key===`Escape`){p(),e.preventDefault();return}if(e.key===`ArrowDown`){e.preventDefault(),a=Math.min(a+1,o.length-1),g();return}if(e.key===`ArrowUp`){e.preventDefault(),a=Math.max(a-1,0),g();return}if(e.key===`Enter`){e.preventDefault(),a>=0&&y(a);return}}t.addEventListener(`input`,function(){m(t.value)}),n.addEventListener(`click`,function(e){var t=e.target.closest(`.search-result`);t&&(e.preventDefault(),y(parseInt(t.getAttribute(`data-index`),10)))}),r&&r.addEventListener(`click`,f);var x=document.getElementById(`search-open-mobile`);x&&x.addEventListener(`click`,f),document.addEventListener(`keydown`,function(e){(e.ctrlKey||e.metaKey)&&e.key===`k`&&(e.preventDefault(),f()),e.key===`/`&&!S(e.target)&&(e.preventDefault(),f())}),e.addEventListener(`click`,function(t){t.target===e&&p()});function S(e){var t=e.tagName;return t===`INPUT`||t===`TEXTAREA`||t===`SELECT`||e.isContentEditable}}`requestIdleCallback`in window?window.requestIdleCallback(e,{timeout:250}):window.addEventListener(`load`,e,{once:!0})})()})(); \ No newline at end of file diff --git a/docs/sourcey/sponsor_logos/backbase.png b/docs/sourcey/sponsor_logos/backbase.png new file mode 100644 index 0000000000000000000000000000000000000000..22acf3aac8e93f4d09f2e4c31502f85a209da4db GIT binary patch literal 5757 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 Wn%C=%XDnxTusSdUjWTtIr~d;?(<52{ literal 0 HcmV?d00001 diff --git a/docs/sourcey/sponsor_logos/cirrus_labs.jpg b/docs/sourcey/sponsor_logos/cirrus_labs.jpg new file mode 100644 index 0000000000000000000000000000000000000000..3bec84f0a22693cde05118fa3c241ed9e89cf389 GIT binary patch literal 3204 zcmd6odpOkF8pqd|F&9Mc#x)I@5{hxD6GIMC$8kxaY12(ECA%U+F{o68bRo(m_Y%{% z#x9i0D4kG>klTboE|c4j#_zXh?|q(qcDw%A=RD`x&wiihyPjvgYprLk&wAIpUZfN0 z2Il}Ci^XAu@i-igK){QL$*d3)6%`{&NlVD6D5|NdC@L$j($LjfwR$~CS($9ScKwEp z6beO6Ym=#o{uW&Wiav@!Ac%>IDXdtbps%j1uK!;fQVS&Upb0dgQLBNFBnmBwLh4bO z0HB0XKO6YBp@h&FVJr?$5D{GogivU-5C$zQjKK(Ih6=_2Mp9TxeWL|d+HpT_^>G>f zh=eb2`P5|eHwr(|Yj=j7()-@R8{Qd(AC z@vyS$XQ;STEwfn?w`EqmZZn~0nS zWk8en6VlH_e+(${elgtO9UDLKlCggkG|y$xo}k08EB+f_E=+g?0J}k02MXkQFCQKnW9*w;>|ZaO;%lA z=|cvY(SJ-iNrVdCMw}7VdQ+@TPwr zD8Dt>y-Djlsq9T8JUQf|)C9}VsV>`a!#t~5m9O@{4++AWqH zg_ouRK^}Wq_!=gbcS4W$xn?vdt_NpNHvDMg-h!LP5)LOG+$L`FeYk1OpOb= z_Od@z{DfKA{4Tl|`@M)s_l^#dgGw{)AGLw71_It8U_0P#|K_h#P-T51sK~c`$?sg4 z=fCRwEN)9U**_p^jhf5kGXq%=%G=Mmcf2H-Hxn#Lb_m6uuyaE|6yp_xYaA*F_p9(N z*yx2R$ZJ^(J{#1xFhTzFM$7psUMCqGJ4I3RM*ni_{`dirCoy3_8gda_ZXMN!I6|vN zK#k9L>E~b-Z+8jtdC6xwuZub=Z%3Ul#R1f8hIsiSCZ{LA8ee=d;qg>!{u1c}TvHg5 zb7qA1Lw(y=FR9{{&TYzO-v?LDKDoh4fB>#N1$^rI)Nzt){bRUG7INL0wyU5>jx22Hj!z#6Y7-uAwBZ{Ht*m7`SdyJs3jzl(r@Ej<5a zv5-6%QvtQ&I!axdJf_p=6>yZP;BgDl_}&OOH`7ovyKyWXlIr7_tGTy%s571h5B4o7 z%-Qn^{=6($x?e7?R+XYXw5O?a4Bu0es5FxyA^PnK^JaSZ zY~Y|@NQZ5y`k~ayQ`~5*TYM|poapTG%E&{AuPt1h^CGE3pEG==xkRfI#U9^H9k8Vv z!}MN8zioy@ay~Pc@gGMPER%GWF%mlhV^Y9kO7xP~Zyf)pg#~w}brS*$=^fk4%d9nZ zrF;|^LL}_LiCTUWldgt&q?ESrky+!1j-3Mtz;mnRE4%|@$P)|83qz^!eOp0ND%}{O zs_8mzAs#%oZAPtw1R2NRaSEmA(JE9ip+% zG>#HoLn7DtLW!G(FZ#v#tPIhXwEyhc!RNOifUyFEGOf-y&Nnj`7t>)_(d=Cy0;mQE z=&LhVJJRMM6IwhDhj|IoF)F_NJ4VY31T0Lq;<{#C8q|(fAs{^&0aF866G_z`Dic-|p<8MhO1VQ*df7*KVa(QWBa zBB#O9NXu@;u>^05v!PvQ=oQ~!*hVz6*u!Yo%^>{d_`4&WflQ^Z3jDW<{$Im~y!#Px CQQ(vS literal 0 HcmV?d00001 diff --git a/docs/sourcey/sponsor_logos/elastic.png b/docs/sourcey/sponsor_logos/elastic.png new file mode 100644 index 0000000000000000000000000000000000000000..393e6711c45f58934ffc04bd8278b9872c44bf44 GIT binary patch literal 23741 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 literal 0 HcmV?d00001 diff --git a/docs/sourcey/sponsor_logos/jooq.jpg b/docs/sourcey/sponsor_logos/jooq.jpg new file mode 100644 index 0000000000000000000000000000000000000000..7a64f773d615adaa24276c8e47bdd6da063f7b2e GIT binary patch literal 3559 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 R_uw*6=R(4QI|Jjt{}&3q{`~*| literal 0 HcmV?d00001 diff --git a/docs/sourcey/sponsor_logos/spotify.png b/docs/sourcey/sponsor_logos/spotify.png new file mode 100644 index 0000000000000000000000000000000000000000..41f149f713b529dae1abc0c49ab7550bbf959b9e GIT binary patch literal 4336 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 literal 0 HcmV?d00001 diff --git a/docs/sourcey/sponsor_logos/vivy.png b/docs/sourcey/sponsor_logos/vivy.png new file mode 100644 index 0000000000000000000000000000000000000000..2faa4742dd1c90956794ea1e0b06471cc35dfd13 GIT binary patch literal 4170 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 literal 0 HcmV?d00001 diff --git a/docs/sourcey/test-framework-integration/junit-5.html b/docs/sourcey/test-framework-integration/junit-5.html new file mode 100644 index 00000000000..2e43b2cadf6 --- /dev/null +++ b/docs/sourcey/test-framework-integration/junit-5.html @@ -0,0 +1,85 @@ + +Jupiter / JUnit 5 - Testcontainers for Java Sourcey Reference
    Integration

    Jupiter / JUnit 5

    This module provides an API that is based on the JUnit Jupiter extension model.

    This module provides an API that is based on the JUnit Jupiter extension model.

    +

    The extension supports two modes:

    +
      +
    • containers that are restarted for every test method
    • +
    • containers that are shared between all methods of a test class
    • +
    +

    Note that Jupiter/JUnit 5 integration is packaged as a separate library JAR; see below for details.

    +

    Extension

    +

    Jupiter integration is provided by means of the @Testcontainers annotation.

    +

    The extension finds all fields that are annotated with @Container and calls their container lifecycle +methods (methods on the Startable interface). Containers declared as static fields will be shared between test +methods. They will be started only once before any test method is executed and stopped after the last test method has +executed. Containers declared as instance fields will be started and stopped for every test method.

    +

    Note: This extension has only been tested with sequential test execution. Using it with parallel test execution is +unsupported and may have unintended side effects.

    +

    Example:

    + +

    Mixed Lifecycle inside_block:testClass

    + + +

    Examples

    +

    To use the Testcontainers extension annotate your test class with @Testcontainers.

    +

    Restarted containers

    +

    To define a restarted container, define an instance field inside your test class and annotate it with +the @Container annotation.

    + +

    Restarted Containers inside_block:testClass

    + + + +

    Shared containers

    +

    Shared containers are defined as static fields in a top level test class and have to be annotated with @Container. +Note that shared containers can't be declared inside nested test classes. +This is because nested test classes have to be defined non-static and can't therefore have static fields.

    + +

    Shared Container lines:18-23,32-33,35-36

    + + +

    Singleton containers

    +

    Note that the singleton container pattern is also an option when +using JUnit 5.

    +

    Limitations

    +

    This extension has only been tested with sequential test execution. Using it with parallel test execution is unsupported and may have unintended side effects.

    +

    Adding Testcontainers JUnit 5 support to your project dependencies

    +

    Add the following dependency to your pom.xml/build.gradle file:

    +

    Gradle

    +
    +
    + +
    +
    testImplementation "org.testcontainers:testcontainers-junit-jupiter:{{latest_version}}"
    +

    Maven

    +
    +
    + +
    +
    &lt;dependency&gt;
    +    &lt;groupId&gt;org.testcontainers</groupId>
    +    &lt;artifactId&gt;testcontainers-junit-jupiter</artifactId>
    +    &lt;version&gt;{{latest_version}}</version>
    +    &lt;scope&gt;test</scope>
    +</dependency>
    +
    \ No newline at end of file diff --git a/docs/sourcey/testcontainers-logo.svg b/docs/sourcey/testcontainers-logo.svg new file mode 100644 index 00000000000..4b099f34a8e --- /dev/null +++ b/docs/sourcey/testcontainers-logo.svg @@ -0,0 +1,22 @@ + + + Testcontainers + + + + + + + + + + + + + + + + + + + \ No newline at end of file