├── .all-contributorsrc ├── .gitattributes ├── .github ├── CODEOWNERS ├── ISSUE_TEMPLATE │ ├── bug_report.yml │ └── feature_request.md ├── PULL_REQUEST_TEMPLATE.md ├── dependabot.yml ├── project.yml └── workflows │ ├── build.yml │ ├── hooks │ └── pre-prepare-release.sh │ ├── pre-release.yml │ ├── quarkus-snapshot.yaml │ ├── release-perform.yml │ └── release-prepare.yml ├── .gitignore ├── .idea └── icon.svg ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── deployment-testing ├── pom.xml └── src │ └── main │ └── java │ └── io │ └── quarkiverse │ └── quinoa │ └── deployment │ └── testing │ └── QuinoaQuarkusUnitTest.java ├── deployment ├── pom.xml └── src │ ├── main │ ├── java │ │ ├── com │ │ │ └── github │ │ │ │ └── eirslett │ │ │ │ └── maven │ │ │ │ └── plugins │ │ │ │ └── frontend │ │ │ │ └── lib │ │ │ │ ├── PackageManagerInstallFactory.java │ │ │ │ └── VertxFileDownloader.java │ │ └── io │ │ │ └── quarkiverse │ │ │ └── quinoa │ │ │ └── deployment │ │ │ ├── ForwardedDevProcessor.java │ │ │ ├── QuinoaProcessor.java │ │ │ ├── SslUtil.java │ │ │ ├── config │ │ │ ├── DevServerConfig.java │ │ │ ├── FrameworkConfig.java │ │ │ ├── PackageManagerCommandConfig.java │ │ │ ├── PackageManagerInstallAuthConfig.java │ │ │ ├── PackageManagerInstallConfig.java │ │ │ ├── QuinoaConfig.java │ │ │ └── delegate │ │ │ │ ├── DevServerConfigDelegate.java │ │ │ │ ├── PackageManagerCommandConfigDelegate.java │ │ │ │ └── QuinoaConfigDelegate.java │ │ │ ├── devui │ │ │ └── QuinoaDevUIProcessor.java │ │ │ ├── framework │ │ │ ├── FrameworkConfigOverrideFactory.java │ │ │ ├── FrameworkType.java │ │ │ └── override │ │ │ │ ├── AngularFramework.java │ │ │ │ ├── GenericFramework.java │ │ │ │ ├── NextFramework.java │ │ │ │ └── ReactFramework.java │ │ │ ├── items │ │ │ ├── BuiltResourcesBuildItem.java │ │ │ ├── ConfiguredQuinoaBuildItem.java │ │ │ ├── ForwardedDevServerBuildItem.java │ │ │ ├── InstalledPackageManagerBuildItem.java │ │ │ ├── PublishedPackageBuildItem.java │ │ │ └── TargetDirBuildItem.java │ │ │ └── packagemanager │ │ │ ├── PackageManagerInstall.java │ │ │ ├── PackageManagerRunner.java │ │ │ └── types │ │ │ ├── ConfiguredPackageManager.java │ │ │ ├── PackageManager.java │ │ │ └── PackageManagerType.java │ └── resources │ │ └── dev-ui │ │ ├── qwc-quinoa-card.js │ │ └── qwc-quinoa-log.js │ └── test │ ├── empty-webui │ └── .gitkeep │ ├── java │ └── io │ │ └── quarkiverse │ │ └── quinoa │ │ ├── deployment │ │ └── framework │ │ │ ├── FrameworkTypeTest.java │ │ │ └── override │ │ │ └── AngularFrameworkTest.java │ │ └── test │ │ ├── QuinoaAbsoluteUIDirTest.java │ │ ├── QuinoaAlreadyInstalledTest.java │ │ ├── QuinoaCIConfigTest.java │ │ ├── QuinoaDefaultConfigTest.java │ │ ├── QuinoaForceInstallTest.java │ │ ├── QuinoaIgnorePathPrefixesConfigTest.java │ │ ├── QuinoaInvalidBuildDirTest.java │ │ ├── QuinoaNoDirTest.java │ │ ├── QuinoaNoPackageJsonTest.java │ │ ├── QuinoaPackageManagerInstallCommandOverrideTest.java │ │ ├── QuinoaPackageManagerInstallTest.java │ │ ├── QuinoaPackageManagerInstallWithSpaceTest.java │ │ ├── QuinoaPackageManagerLockfileDetectNPMTest.java │ │ ├── QuinoaPackageManagerLockfileDetectPNPMTest.java │ │ ├── QuinoaPackageManagerLockfileDetectYarnTest.java │ │ ├── QuinoaPackageManagerNPMOverrideBuildEnvTest.java │ │ ├── QuinoaPackageManagerNPMOverrideEnvTest.java │ │ ├── QuinoaPackageManagerPublishTest.java │ │ ├── QuinoaPackageManagerSetYarnConfigTest.java │ │ ├── QuinoaPackageManagerSetYarnOtherConfigTest.java │ │ ├── QuinoaPathPrefixesRESTConfigRelativeRootPathTest.java │ │ ├── QuinoaPathPrefixesRESTConfigRootPathTest.java │ │ ├── QuinoaPathPrefixesRESTConfigTest.java │ │ ├── QuinoaPathPrefixesRESTConfigUiRootPathTest.java │ │ └── devmode │ │ ├── ClassicDevModeCompressionTest.java │ │ ├── ClassicDevModeTest.java │ │ ├── ForwardedDevModeCompressionTest.java │ │ └── ForwardedDevModeTest.java │ ├── resources │ ├── application.properties │ ├── frameworks │ │ ├── angular-args.json │ │ ├── angular-envs.json │ │ ├── angular-exact.json │ │ ├── angular │ │ │ ├── builder-application-output-obj-browser.json │ │ │ ├── builder-application-output-obj-no-browser.json │ │ │ ├── builder-application-output-str.json │ │ │ └── builder-browser-output-str.json │ │ ├── react-create-app-different-dev-script-envs.json │ │ ├── react-create-app-different-dev-script.json │ │ ├── react-create-app-exact.json │ │ ├── react-create-app-multiple-nok.json │ │ ├── react-create-app-multiple-ok-guess-command.json │ │ ├── react-create-app-multiple-ok-guess.json │ │ └── react-create-app-multiple-ok.json │ └── lockfiles │ │ ├── package-lock.json │ │ ├── pnpm-lock.yaml │ │ └── yarn.lock │ └── webui │ ├── .gitignore │ ├── package.json │ ├── public │ ├── some-image.svg │ └── some-page.html │ └── server.js ├── docs ├── antora.yml ├── modules │ └── ROOT │ │ ├── assets │ │ └── images │ │ │ ├── node_logo.svg │ │ │ ├── npm-logo.svg │ │ │ ├── plus-sign.svg │ │ │ ├── quarkus.svg │ │ │ ├── quinoa-build.excalidraw │ │ │ ├── quinoa-build.png │ │ │ ├── quinoa-proxy-dev.excalidraw │ │ │ ├── quinoa-proxy-dev.png │ │ │ ├── quinoa-runtime-prod.excalidraw │ │ │ └── quinoa-runtime-prod.png │ │ ├── nav.adoc │ │ └── pages │ │ ├── advanced-guides.adoc │ │ ├── config-reference.adoc │ │ ├── includes │ │ ├── attributes.adoc │ │ └── quarkus-quinoa.adoc │ │ ├── index.adoc │ │ ├── main-concepts.adoc │ │ ├── testing.adoc │ │ └── web-frameworks.adoc ├── pom.xml └── templates │ └── includes │ └── attributes.adoc ├── integration-tests ├── pom.xml └── src │ ├── main │ ├── java │ │ └── io │ │ │ └── quarkiverse │ │ │ └── quinoa │ │ │ └── it │ │ │ └── QuinoaResource.java │ ├── resources │ │ ├── META-INF │ │ │ └── resources │ │ │ │ └── index.html │ │ └── application.properties │ ├── ui-angular-esbuild │ │ ├── .gitignore │ │ ├── README.md │ │ ├── angular.json │ │ ├── package-lock.json │ │ ├── package.json │ │ ├── public │ │ │ └── favicon.ico │ │ ├── src │ │ │ ├── app │ │ │ │ ├── app.component.css │ │ │ │ ├── app.component.html │ │ │ │ ├── app.component.spec.ts │ │ │ │ ├── app.component.ts │ │ │ │ ├── app.config.ts │ │ │ │ └── app.routes.ts │ │ │ ├── index.html │ │ │ ├── main.ts │ │ │ └── styles.css │ │ ├── tsconfig.app.json │ │ ├── tsconfig.json │ │ └── tsconfig.spec.json │ ├── ui-angular │ │ ├── .gitignore │ │ ├── .yarn │ │ │ └── releases │ │ │ │ └── yarn-3.6.3.cjs │ │ ├── .yarnrc.yml │ │ ├── README.md │ │ ├── angular.json │ │ ├── karma.conf.js │ │ ├── package-lock.json │ │ ├── package.json │ │ ├── src │ │ │ ├── app │ │ │ │ ├── app-routing.module.ts │ │ │ │ ├── app.component.html │ │ │ │ ├── app.component.scss │ │ │ │ ├── app.component.spec.ts │ │ │ │ ├── app.component.ts │ │ │ │ └── app.module.ts │ │ │ ├── assets │ │ │ │ └── .gitkeep │ │ │ ├── environments │ │ │ │ ├── environment.prod.ts │ │ │ │ └── environment.ts │ │ │ ├── favicon.ico │ │ │ ├── image with spaces.svg │ │ │ ├── index.html │ │ │ ├── main.ts │ │ │ ├── polyfills.ts │ │ │ ├── styles.scss │ │ │ └── test.ts │ │ ├── tsconfig.app.json │ │ ├── tsconfig.json │ │ ├── tsconfig.spec.json │ │ └── yarn.lock │ ├── ui-lit │ │ ├── package-lock.json │ │ ├── package.json │ │ ├── public │ │ │ ├── app.html │ │ │ └── favicon.ico │ │ ├── src │ │ │ └── simple-greeting.js │ │ └── webpack.config.js │ ├── ui-react │ │ ├── .gitignore │ │ ├── README.md │ │ ├── package-lock.json │ │ ├── package.json │ │ ├── public │ │ │ ├── favicon.ico │ │ │ ├── index.html │ │ │ ├── logo192.png │ │ │ ├── logo512.png │ │ │ ├── manifest.json │ │ │ └── robots.txt │ │ ├── src │ │ │ ├── App.css │ │ │ ├── App.js │ │ │ ├── App.test.js │ │ │ ├── index.css │ │ │ ├── index.js │ │ │ ├── logo.svg │ │ │ ├── reportWebVitals.js │ │ │ └── setupTests.js │ │ └── yarn.lock │ └── ui-vue │ │ ├── .eslintrc.cjs │ │ ├── .gitignore │ │ ├── .prettierrc.json │ │ ├── README.md │ │ ├── index.html │ │ ├── package.json │ │ ├── public │ │ └── favicon.ico │ │ ├── src │ │ ├── App.vue │ │ ├── assets │ │ │ ├── base.css │ │ │ ├── logo.svg │ │ │ └── main.css │ │ ├── components │ │ │ ├── HelloWorld.vue │ │ │ ├── TheWelcome.vue │ │ │ ├── WelcomeItem.vue │ │ │ ├── __tests__ │ │ │ │ └── HelloWorld.spec.js │ │ │ └── icons │ │ │ │ ├── IconCommunity.vue │ │ │ │ ├── IconDocumentation.vue │ │ │ │ ├── IconEcosystem.vue │ │ │ │ ├── IconSupport.vue │ │ │ │ └── IconTooling.vue │ │ ├── main.js │ │ ├── router │ │ │ └── index.js │ │ └── views │ │ │ ├── AboutView.vue │ │ │ └── HomeView.vue │ │ ├── vite.config.js │ │ ├── vitest.config.js │ │ └── yarn.lock │ └── test │ ├── java │ └── io │ │ └── quarkiverse │ │ └── quinoa │ │ └── it │ │ ├── QuinoaCodestartTest.java │ │ ├── QuinoaRootPathTest.java │ │ ├── QuinoaUIAngularEsBuildTest.java │ │ ├── QuinoaUIAngularTest.java │ │ ├── QuinoaUIIT.java │ │ ├── QuinoaUILitTest.java │ │ ├── QuinoaUIReactJustBuildTest.java │ │ ├── QuinoaUIReactTest.java │ │ ├── QuinoaUIVueTest.java │ │ ├── QuinoaUIYarnTest.java │ │ ├── QuinoaUiRootPathTest.java │ │ └── TestProfiles.java │ └── resources │ └── __snapshots__ │ └── QuinoaCodestartTest │ └── testContent │ └── dir-tree.snapshot ├── pom.xml ├── runtime ├── pom.xml └── src │ └── main │ ├── codestarts │ └── quarkus │ │ └── quinoa-codestart │ │ ├── base │ │ ├── ..gitignore │ │ ├── README.tpl.qute.md │ │ └── src │ │ │ └── main │ │ │ ├── java │ │ │ └── .gitkeep │ │ │ ├── resources │ │ │ ├── META-INF │ │ │ │ └── resources │ │ │ │ │ └── index.entry.qute.html │ │ │ └── application.yml │ │ │ └── webui │ │ │ ├── counter.js │ │ │ ├── index.html │ │ │ ├── main.js │ │ │ ├── package-lock.json │ │ │ ├── package.json │ │ │ ├── public │ │ │ ├── quarkus.svg │ │ │ └── vite.svg │ │ │ └── style.css │ │ └── codestart.yml │ ├── java │ └── io │ │ └── quarkiverse │ │ └── quinoa │ │ ├── QuinoaDevProxyHandler.java │ │ ├── QuinoaDevProxyHandlerConfig.java │ │ ├── QuinoaDevWebSocketProxyHandler.java │ │ ├── QuinoaNetworkConfiguration.java │ │ ├── QuinoaRecorder.java │ │ └── QuinoaSPARoutingHandler.java │ └── resources │ └── META-INF │ └── quarkus-extension.yaml └── testing ├── pom.xml └── src └── main └── java └── io └── quarkiverse └── quinoa └── testing └── QuinoaTestProfiles.java /.gitattributes: -------------------------------------------------------------------------------- 1 | # Set the default behavior, in case people don't have core.autocrlf set. 2 | * text=auto 3 | 4 | # Explicitly declare text files you want to always be normalized and converted 5 | # to native line endings on checkout. 6 | *.c text 7 | *.h text 8 | *.java text 9 | *.css text 10 | *.js text 11 | *.xml text 12 | *.dtd text 13 | *.xsl text 14 | *.properties text 15 | *.txt text 16 | *.svg text 17 | *.yml text 18 | *.md text 19 | 20 | # Denote all files that are truly binary and should not be modified. 21 | *.png binary 22 | *.gif binary 23 | *.jpg binary 24 | *.jpeg binary 25 | *.eot binary 26 | *.ttf binary 27 | *.woff binary 28 | *.woff2 binary 29 | * text eol=lf 30 | 31 | # Denote all files that are truly binary and should not be modified. 32 | *.png binary 33 | *.jpg binary -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | # Lines starting with '#' are comments. 2 | # Each line is a file pattern followed by one or more owners. 3 | 4 | # More details are here: https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners 5 | 6 | # The '*' pattern is global owners. 7 | 8 | # Order is important. The last matching pattern has the most precedence. 9 | # The folders are ordered as follows: 10 | 11 | # In each subsection folders are ordered first by depth, then alphabetically. 12 | # This should make it easy to add new rules without breaking existing ones. 13 | 14 | * @quarkiverse/quarkiverse-quinoa 15 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.yml: -------------------------------------------------------------------------------- 1 | name: Bug report 2 | description: Create a report to help Quinoa improve 3 | title: 'Issue Title' 4 | labels: ['Status: needs triage'] 5 | body: 6 | - type: textarea 7 | id: description 8 | attributes: 9 | label: Describe the bug 10 | description: A clear and concise description of what the bug is. 11 | validations: 12 | required: true 13 | - type: input 14 | id: quinoa-version 15 | attributes: 16 | label: Quinoa version 17 | placeholder: x.x.x 18 | validations: 19 | required: true 20 | - type: input 21 | id: quarkus-version 22 | attributes: 23 | label: Quarkus version 24 | placeholder: x.x.x 25 | validations: 26 | required: true 27 | - type: dropdown 28 | id: engine 29 | attributes: 30 | label: Build / Runtime 31 | multiple: false 32 | options: 33 | - Vite 34 | - Angular 35 | - Create React App (CRA) 36 | - Next.js 37 | - Other 38 | validations: 39 | required: true 40 | - type: dropdown 41 | id: package-manager 42 | attributes: 43 | label: Package Manager 44 | multiple: false 45 | options: 46 | - NPM 47 | - PNPM 48 | - YARN 49 | - OTHER 50 | - type: textarea 51 | id: reproduce-steps 52 | attributes: 53 | label: Steps to reproduce the behavior 54 | description: A clear and concise description of how to make the issue happen. 55 | placeholder: > 56 | 1. Go to '...' 57 | 2. Click on '....' 58 | 3. Scroll down to '....' 59 | 4. See error 60 | validations: 61 | required: false 62 | - type: textarea 63 | id: expected-behavior 64 | attributes: 65 | label: Expected behavior 66 | description: A clear and concise description of what you expected to happen. 67 | validations: 68 | required: false 69 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: feature 6 | assignees: '' 7 | 8 | --- 9 | 10 | ## Feature idea 11 | 12 | 13 | ## Additional information 14 | 15 | 16 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 2 | ## Describe your changes 3 | 4 | 5 | ## Fixes Issue 6 | 7 | 8 | 9 | 15 | 16 | ## Check List (Check all the applicable boxes) 17 | 18 | - [ ] My code follows the code style of this project. 19 | - [ ] My change requires changes to the documentation. 20 | - [ ] I have updated the documentation accordingly. 21 | - [ ] All new and existing tests passed. 22 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | # To get started with Dependabot version updates, you'll need to specify which 2 | # package ecosystems to update and where the package manifests are located. 3 | # Please see the documentation for all configuration options: 4 | # https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates 5 | 6 | version: 2 7 | updates: 8 | - package-ecosystem: "maven" 9 | directory: "/" 10 | schedule: 11 | interval: "daily" 12 | ignore: 13 | - dependency-name: "io.quarkus:quarkus-bom" 14 | - dependency-name: "io.quarkus:quarkus-maven-plugin" 15 | - dependency-name: "io.quarkus:quarkus-extension-processor" 16 | - dependency-name: "io.quarkus:quarkus-extension-maven-plugin" 17 | groups: 18 | quarkus: 19 | patterns: 20 | - "io.quarkus*" 21 | - "quarkus*" 22 | quarkiverse: 23 | patterns: 24 | - "io.quarkiverse*" 25 | dependencies: 26 | patterns: 27 | - "*" 28 | exclude-patterns: 29 | - "io.quarkus*" 30 | - "quarkus*" 31 | - "io.quarkiverse*" 32 | - package-ecosystem: "github-actions" 33 | directory: "/" 34 | schedule: 35 | interval: "daily" 36 | -------------------------------------------------------------------------------- /.github/project.yml: -------------------------------------------------------------------------------- 1 | release: 2 | current-version: 2.5.4 3 | next-version: 999-SNAPSHOT 4 | 5 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: Build and Test Java Application 2 | 3 | on: 4 | push: 5 | branches: 6 | - "main" 7 | paths-ignore: 8 | - '.gitignore' 9 | - 'CODEOWNERS' 10 | - 'LICENSE' 11 | - '*.md' 12 | - '*.adoc' 13 | - '*.txt' 14 | - '.all-contributorsrc' 15 | pull_request: 16 | paths-ignore: 17 | - '.gitignore' 18 | - 'CODEOWNERS' 19 | - 'LICENSE' 20 | - '*.md' 21 | - '*.adoc' 22 | - '*.txt' 23 | - '.all-contributorsrc' 24 | 25 | jobs: 26 | build-linux: 27 | 28 | runs-on: ubuntu-latest 29 | 30 | steps: 31 | - uses: actions/checkout@v4 32 | 33 | - name: Set up JDK 17 34 | uses: actions/setup-java@v4 35 | with: 36 | distribution: temurin 37 | java-version: 17 38 | 39 | - name: Get Date 40 | id: get-date 41 | run: | 42 | echo "date=$(/bin/date -u "+%Y-%m")" >> $GITHUB_OUTPUT 43 | shell: bash 44 | - name: Cache Maven Repository 45 | id: cache-maven 46 | uses: actions/cache@v4 47 | with: 48 | path: ~/.m2/repository 49 | # resulting in faster build times. 50 | key: maven-repo-${{ runner.os }}-${{ hashFiles('**/pom.xml') }} 51 | - name: Install pnpm 52 | run: npm install -g pnpm 53 | - name: Maven Version 54 | run: mvn --version 55 | - name: Build with Maven 56 | run: mvn -B formatter:validate install --file pom.xml 57 | - name: Build with Maven (Native) 58 | run: mvn -B install -Dnative -Dquarkus.native.container-build -Dnative.surefire.skip 59 | build-windows: 60 | runs-on: windows-latest 61 | steps: 62 | - uses: actions/checkout@v4 63 | 64 | - name: Set up JDK 17 65 | uses: actions/setup-java@v4 66 | with: 67 | distribution: temurin 68 | java-version: 17 69 | 70 | - name: Get Date 71 | id: get-date 72 | run: | 73 | echo "date=$(/bin/date -u "+%Y-%m")" >> $GITHUB_OUTPUT 74 | shell: bash 75 | - name: Cache Maven Repository 76 | id: cache-maven 77 | uses: actions/cache@v4 78 | with: 79 | path: ~/.m2/repository 80 | # resulting in faster build times. 81 | key: maven-repo-${{ runner.os }}-${{ hashFiles('**/pom.xml') }} 82 | - name: Install pnpm 83 | run: npm install -g pnpm@~8.6.12 84 | - name: Maven Version 85 | run: mvn --version 86 | - name: Build with Maven 87 | run: mvn -B install --file pom.xml 88 | -------------------------------------------------------------------------------- /.github/workflows/hooks/pre-prepare-release.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | #------------------------------------- 3 | # Hook invoked by the release workflow 4 | #------------------------------------- 5 | 6 | # Install pnpm 7 | npm install -g pnpm@~8.6.12 8 | -------------------------------------------------------------------------------- /.github/workflows/pre-release.yml: -------------------------------------------------------------------------------- 1 | name: Quarkiverse Pre Release 2 | 3 | on: 4 | pull_request: 5 | paths: 6 | - '.github/project.yml' 7 | 8 | concurrency: 9 | group: ${{ github.workflow }}-${{ github.ref }} 10 | cancel-in-progress: true 11 | 12 | jobs: 13 | pre-release: 14 | name: Pre-Release 15 | uses: quarkiverse/.github/.github/workflows/pre-release.yml@main 16 | secrets: inherit 17 | -------------------------------------------------------------------------------- /.github/workflows/quarkus-snapshot.yaml: -------------------------------------------------------------------------------- 1 | name: "Quarkus ecosystem CI" 2 | on: 3 | workflow_dispatch: 4 | watch: 5 | types: [started] 6 | 7 | # For this CI to work, ECOSYSTEM_CI_TOKEN needs to contain a GitHub with rights to close the Quarkus issue that the user/bot has opened, 8 | # while 'ECOSYSTEM_CI_REPO_PATH' needs to be set to the corresponding path in the 'quarkusio/quarkus-ecosystem-ci' repository 9 | 10 | env: 11 | ECOSYSTEM_CI_REPO: quarkusio/quarkus-ecosystem-ci 12 | ECOSYSTEM_CI_REPO_FILE: context.yaml 13 | JAVA_VERSION: 17 14 | 15 | ######################### 16 | # Repo specific setting # 17 | ######################### 18 | 19 | ECOSYSTEM_CI_REPO_PATH: quarkiverse-quinoa 20 | 21 | concurrency: 22 | group: ${{ github.workflow }}-${{ github.ref }} 23 | cancel-in-progress: true 24 | 25 | defaults: 26 | run: 27 | shell: bash 28 | 29 | jobs: 30 | build: 31 | name: "Build against latest Quarkus snapshot" 32 | runs-on: ubuntu-latest 33 | # Allow to manually launch the ecosystem CI in addition to the bots 34 | if: github.actor == 'quarkusbot' || github.actor == 'quarkiversebot' || github.actor == 'ia3andy' || github.actor == 'melloware' 35 | 36 | steps: 37 | - name: Install yq 38 | uses: dcarbone/install-yq-action@v1 39 | 40 | - name: Set up Java 41 | uses: actions/setup-java@v4 42 | with: 43 | distribution: temurin 44 | java-version: ${{ env.JAVA_VERSION }} 45 | 46 | - name: Checkout repo 47 | uses: actions/checkout@v4 48 | with: 49 | path: current-repo 50 | 51 | - name: Checkout Ecosystem 52 | uses: actions/checkout@v4 53 | with: 54 | repository: ${{ env.ECOSYSTEM_CI_REPO }} 55 | path: ecosystem-ci 56 | 57 | - name: Install pnpm 58 | run: npm install -g pnpm@~8.6.12 59 | 60 | - name: Setup and Run Tests 61 | run: ./ecosystem-ci/setup-and-test 62 | env: 63 | ECOSYSTEM_CI_TOKEN: ${{ secrets.ECOSYSTEM_CI_TOKEN }} 64 | -------------------------------------------------------------------------------- /.github/workflows/release-perform.yml: -------------------------------------------------------------------------------- 1 | name: Quarkiverse Perform Release 2 | run-name: Perform ${{github.event.inputs.tag || github.ref_name}} Release 3 | on: 4 | push: 5 | tags: 6 | - '*' 7 | workflow_dispatch: 8 | inputs: 9 | tag: 10 | description: 'Tag to release' 11 | required: true 12 | 13 | permissions: 14 | attestations: write 15 | id-token: write 16 | contents: read 17 | 18 | concurrency: 19 | group: ${{ github.workflow }}-${{ github.ref }} 20 | cancel-in-progress: true 21 | 22 | jobs: 23 | perform-release: 24 | name: Perform Release 25 | uses: quarkiverse/.github/.github/workflows/perform-release.yml@main 26 | secrets: inherit 27 | with: 28 | version: ${{github.event.inputs.tag || github.ref_name}} 29 | -------------------------------------------------------------------------------- /.github/workflows/release-prepare.yml: -------------------------------------------------------------------------------- 1 | name: Quarkiverse Prepare Release 2 | 3 | on: 4 | workflow_dispatch: 5 | pull_request: 6 | types: [ closed ] 7 | paths: 8 | - '.github/project.yml' 9 | 10 | concurrency: 11 | group: ${{ github.workflow }}-${{ github.ref }} 12 | cancel-in-progress: true 13 | 14 | jobs: 15 | prepare-release: 16 | name: Prepare Release 17 | if: ${{ github.event_name == 'workflow_dispatch' || github.event.pull_request.merged == true}} 18 | uses: quarkiverse/.github/.github/workflows/prepare-release.yml@main 19 | secrets: inherit 20 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled class file 2 | *.class 3 | 4 | # Log file 5 | *.log 6 | 7 | # BlueJ files 8 | *.ctxt 9 | 10 | # Mobile Tools for Java (J2ME) 11 | .mtj.tmp/ 12 | 13 | # Package Files # 14 | *.jar 15 | *.war 16 | *.nar 17 | *.ear 18 | *.zip 19 | *.tar.gz 20 | *.rar 21 | 22 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 23 | hs_err_pid* 24 | 25 | # Eclipse 26 | .project 27 | .classpath 28 | .settings/ 29 | bin/ 30 | 31 | .quarkus/ 32 | 33 | # IntelliJ 34 | .idea 35 | *.ipr 36 | *.iml 37 | *.iws 38 | 39 | # NetBeans 40 | nb-configuration.xml 41 | 42 | # Visual Studio Code 43 | .vscode 44 | .factorypath 45 | 46 | # OSX 47 | .DS_Store 48 | 49 | # Vim 50 | *.swp 51 | *.swo 52 | 53 | # patch 54 | *.orig 55 | *.rej 56 | 57 | # Gradle 58 | .gradle/ 59 | build/ 60 | 61 | # Maven 62 | target/ 63 | pom.xml.tag 64 | pom.xml.releaseBackup 65 | pom.xml.versionsBackup 66 | release.properties 67 | 68 | #npm 69 | **/node_modules/** 70 | **/build/** 71 | **/dist/** 72 | -------------------------------------------------------------------------------- /.idea/icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | ## Contributing at quarkus-quinoa 2 | We are beyond excited to see that you want to contribute! We would love to accept your contributions. Navigate through the following to understand more about contributing. 3 | 4 | ### Prerequisites 5 | - Java 11 6 | - Apache Maven 7 | 8 | ## Follow the Steps 9 | - [Fork the repository](https://github.com/quarkiverse/quarkus-quinoa/fork) 10 | 11 | - Clone the project locally 12 | 13 | ``` 14 | git clone https://github.com/shivam-sharma7/quarkus-quinoa.git 15 | ``` 16 | **Note:** In the place of `shivam-sharma7` you have to add your github username. 17 | 18 | - Create a new branch 19 | 20 | ``` 21 | git checkout -b 22 | ``` 23 | 24 | After creating new branch start making your changes and once the changes done then push your changes and then create a ` pull_request` 25 | - Push your changes 26 | 27 | ``` 28 | git push origin 29 | ``` 30 | 31 | Now you have to wait for the review. The project maintainer will review your PR and once your PR got approve then they will merged it. If you want to support, please give a ⭐ 32 | 33 | ### Things to remember before making changes 34 | 35 | Before making any contribution make sure your local `main` keep up-to-date with upstream `main`. To do that type the following commands. 36 | 37 | - First add upstream 38 | ``` 39 | git remote add upstream https://github.com/quarkiverse/quarkus-quinoa.git 40 | ``` 41 | - Pull all changes from upstream 42 | ``` 43 | git pull upstream main 44 | ``` 45 | - Keep your fork up-to-date 46 | ``` 47 | git push origin main 48 | ``` -------------------------------------------------------------------------------- /deployment-testing/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | 5 | io.quarkiverse.quinoa 6 | quarkus-quinoa-parent 7 | 999-SNAPSHOT 8 | 9 | quarkus-quinoa-deployment-testing 10 | Quarkus - Quinoa - Deployment - Testing 11 | 12 | 13 | io.quarkus 14 | quarkus-junit5-internal 15 | 16 | 17 | io.quarkus 18 | quarkus-junit5 19 | 20 | 21 | org.assertj 22 | assertj-core 23 | 24 | 25 | io.rest-assured 26 | rest-assured 27 | 28 | 29 | -------------------------------------------------------------------------------- /deployment/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | 5 | io.quarkiverse.quinoa 6 | quarkus-quinoa-parent 7 | 999-SNAPSHOT 8 | 9 | quarkus-quinoa-deployment 10 | Quarkus - Quinoa - Deployment 11 | 12 | 13 | io.quarkus 14 | quarkus-vertx-http-deployment 15 | 16 | 17 | io.quarkus 18 | quarkus-rest-server-spi-deployment 19 | 20 | 21 | io.quarkus 22 | quarkus-vertx-http-dev-ui-spi 23 | 24 | 25 | com.github.eirslett 26 | frontend-plugin-core 27 | ${frontend-plugin.version} 28 | 29 | 30 | io.quarkiverse.quinoa 31 | quarkus-quinoa 32 | ${project.version} 33 | 34 | 35 | io.quarkiverse.quinoa 36 | quarkus-quinoa-deployment-testing 37 | ${project.version} 38 | test 39 | 40 | 41 | 42 | 43 | 44 | maven-compiler-plugin 45 | 46 | 47 | 48 | io.quarkus 49 | quarkus-extension-processor 50 | ${quarkus.version} 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | -------------------------------------------------------------------------------- /deployment/src/main/java/com/github/eirslett/maven/plugins/frontend/lib/PackageManagerInstallFactory.java: -------------------------------------------------------------------------------- 1 | package com.github.eirslett.maven.plugins.frontend.lib; 2 | 3 | import java.nio.file.Path; 4 | 5 | import io.vertx.core.Vertx; 6 | 7 | public class PackageManagerInstallFactory { 8 | 9 | private static final Platform defaultPlatform = Platform.guess(); 10 | 11 | private final Path uiDir; 12 | private final Path installDir; 13 | private final CacheResolver cacheResolver; 14 | private final VertxFileDownloader fileDownloader; 15 | private final String userName; 16 | private final String password; 17 | 18 | public PackageManagerInstallFactory(Vertx vertx, Path uiDir, Path installDir, String userName, String password) { 19 | this.uiDir = uiDir; 20 | this.installDir = installDir; 21 | this.cacheResolver = getDefaultCacheResolver(installDir); 22 | this.userName = userName; 23 | this.password = password; 24 | fileDownloader = new VertxFileDownloader(vertx); 25 | } 26 | 27 | public NodeInstaller getNodeInstaller() { 28 | NodeInstaller nodeInstaller = new NodeInstaller(this.getInstallConfig(), new DefaultArchiveExtractor(), fileDownloader); 29 | nodeInstaller.setUserName(this.userName); 30 | nodeInstaller.setPassword(this.password); 31 | return nodeInstaller; 32 | } 33 | 34 | public NPMInstaller getNPMInstaller() { 35 | NPMInstaller npmInstaller = new NPMInstaller(this.getInstallConfig(), new DefaultArchiveExtractor(), fileDownloader); 36 | npmInstaller.setUserName(this.userName); 37 | npmInstaller.setPassword(this.password); 38 | return npmInstaller; 39 | } 40 | 41 | public PnpmInstaller getPnpmInstaller() { 42 | PnpmInstaller pnpmInstaller = new PnpmInstaller(this.getInstallConfig(), new DefaultArchiveExtractor(), fileDownloader); 43 | pnpmInstaller.setUserName(this.userName); 44 | pnpmInstaller.setPassword(this.password); 45 | return pnpmInstaller; 46 | } 47 | 48 | public YarnInstaller getYarnInstaller() { 49 | YarnInstaller yarnInstaller = new YarnInstaller(this.getInstallConfig(), new DefaultArchiveExtractor(), fileDownloader); 50 | yarnInstaller.setUserName(this.userName); 51 | yarnInstaller.setPassword(this.password); 52 | return yarnInstaller; 53 | } 54 | 55 | private NodeExecutorConfig getExecutorConfig() { 56 | return new InstallNodeExecutorConfig(this.getInstallConfig()); 57 | } 58 | 59 | private InstallConfig getInstallConfig() { 60 | return new DefaultInstallConfig(installDir.toFile(), uiDir.toFile(), this.cacheResolver, defaultPlatform); 61 | } 62 | 63 | private static CacheResolver getDefaultCacheResolver(Path root) { 64 | return new DirectoryCacheResolver(root.resolve("cache").toFile()); 65 | } 66 | 67 | } -------------------------------------------------------------------------------- /deployment/src/main/java/io/quarkiverse/quinoa/deployment/SslUtil.java: -------------------------------------------------------------------------------- 1 | package io.quarkiverse.quinoa.deployment; 2 | 3 | import java.net.Socket; 4 | import java.security.KeyManagementException; 5 | import java.security.NoSuchAlgorithmException; 6 | import java.security.SecureRandom; 7 | import java.security.cert.X509Certificate; 8 | 9 | import javax.net.ssl.SSLContext; 10 | import javax.net.ssl.SSLEngine; 11 | import javax.net.ssl.TrustManager; 12 | import javax.net.ssl.X509ExtendedTrustManager; 13 | 14 | public class SslUtil { 15 | private final static X509ExtendedTrustManager NON_VALIDATING_TRUST_MANAGER = new X509ExtendedTrustManager() { 16 | @Override 17 | public void checkClientTrusted(X509Certificate[] chain, String authType, Socket socket) { 18 | } 19 | 20 | @Override 21 | public void checkServerTrusted(X509Certificate[] chain, String authType, Socket socket) { 22 | } 23 | 24 | @Override 25 | public void checkClientTrusted(X509Certificate[] chain, String authType, SSLEngine engine) { 26 | } 27 | 28 | @Override 29 | public void checkServerTrusted(X509Certificate[] chain, String authType, SSLEngine engine) { 30 | } 31 | 32 | @Override 33 | public void checkClientTrusted(X509Certificate[] chain, String authType) { 34 | } 35 | 36 | @Override 37 | public void checkServerTrusted(X509Certificate[] chain, String authType) { 38 | } 39 | 40 | @Override 41 | public X509Certificate[] getAcceptedIssuers() { 42 | return new X509Certificate[0]; 43 | } 44 | }; 45 | 46 | public static SSLContext createNonValidatingSslContext() { 47 | try { 48 | SSLContext sslContext = SSLContext.getInstance("TLS"); 49 | sslContext.init(null, new TrustManager[] { NON_VALIDATING_TRUST_MANAGER }, new SecureRandom()); 50 | return sslContext; 51 | } catch (NoSuchAlgorithmException | KeyManagementException e) { 52 | throw new RuntimeException(e); 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /deployment/src/main/java/io/quarkiverse/quinoa/deployment/config/FrameworkConfig.java: -------------------------------------------------------------------------------- 1 | package io.quarkiverse.quinoa.deployment.config; 2 | 3 | import java.util.Objects; 4 | 5 | import io.quarkus.runtime.annotations.ConfigGroup; 6 | import io.smallrye.config.WithDefault; 7 | 8 | @ConfigGroup 9 | public interface FrameworkConfig { 10 | 11 | static boolean isEqual(FrameworkConfig f1, FrameworkConfig f2) { 12 | if (!Objects.equals(f1.detection(), f2.detection())) { 13 | return false; 14 | } 15 | return true; 16 | } 17 | 18 | /** 19 | * When true, the UI Framework will be auto-detected if possible 20 | */ 21 | @WithDefault("true") 22 | boolean detection(); 23 | } 24 | -------------------------------------------------------------------------------- /deployment/src/main/java/io/quarkiverse/quinoa/deployment/config/PackageManagerInstallAuthConfig.java: -------------------------------------------------------------------------------- 1 | package io.quarkiverse.quinoa.deployment.config; 2 | 3 | import java.util.Objects; 4 | import java.util.Optional; 5 | 6 | import io.quarkus.runtime.annotations.ConfigGroup; 7 | 8 | @ConfigGroup 9 | public interface PackageManagerInstallAuthConfig { 10 | 11 | /** 12 | * The basic authentication username to use for node download. 13 | */ 14 | Optional username(); 15 | 16 | /** 17 | * The basic authentication password to use for node download. 18 | */ 19 | Optional password(); 20 | 21 | static boolean isEqual(PackageManagerInstallAuthConfig p1, PackageManagerInstallAuthConfig p2) { 22 | if (!Objects.equals(p1.username(), p2.username())) { 23 | return false; 24 | } 25 | if (!Objects.equals(p1.password(), p2.password())) { 26 | return false; 27 | } 28 | return true; 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /deployment/src/main/java/io/quarkiverse/quinoa/deployment/config/delegate/DevServerConfigDelegate.java: -------------------------------------------------------------------------------- 1 | package io.quarkiverse.quinoa.deployment.config.delegate; 2 | 3 | import java.util.Optional; 4 | 5 | import io.quarkiverse.quinoa.deployment.config.DevServerConfig; 6 | 7 | public class DevServerConfigDelegate implements DevServerConfig { 8 | private final DevServerConfig delegate; 9 | 10 | public DevServerConfigDelegate(DevServerConfig delegate) { 11 | this.delegate = delegate; 12 | } 13 | 14 | @Override 15 | public boolean enabled() { 16 | return delegate.enabled(); 17 | } 18 | 19 | @Override 20 | public boolean managed() { 21 | return delegate.managed(); 22 | } 23 | 24 | @Override 25 | public Optional port() { 26 | return delegate.port(); 27 | } 28 | 29 | @Override 30 | public String host() { 31 | return delegate.host(); 32 | } 33 | 34 | @Override 35 | public boolean tls() { 36 | return delegate.tls(); 37 | } 38 | 39 | @Override 40 | public boolean tlsAllowInsecure() { 41 | return delegate.tlsAllowInsecure(); 42 | } 43 | 44 | @Override 45 | public Optional checkPath() { 46 | return delegate.checkPath(); 47 | } 48 | 49 | @Override 50 | public boolean websocket() { 51 | return delegate.websocket(); 52 | } 53 | 54 | @Override 55 | public int checkTimeout() { 56 | return delegate.checkTimeout(); 57 | } 58 | 59 | @Override 60 | public boolean logs() { 61 | return delegate.logs(); 62 | } 63 | 64 | @Override 65 | public Optional indexPage() { 66 | return delegate.indexPage(); 67 | } 68 | 69 | @Override 70 | public boolean directForwarding() { 71 | return delegate.directForwarding(); 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /deployment/src/main/java/io/quarkiverse/quinoa/deployment/config/delegate/PackageManagerCommandConfigDelegate.java: -------------------------------------------------------------------------------- 1 | package io.quarkiverse.quinoa.deployment.config.delegate; 2 | 3 | import java.util.Map; 4 | import java.util.Optional; 5 | 6 | import io.quarkiverse.quinoa.deployment.config.PackageManagerCommandConfig; 7 | 8 | public class PackageManagerCommandConfigDelegate implements PackageManagerCommandConfig { 9 | 10 | private final PackageManagerCommandConfig delegate; 11 | 12 | public PackageManagerCommandConfigDelegate(PackageManagerCommandConfig delegate) { 13 | this.delegate = delegate; 14 | } 15 | 16 | @Override 17 | public Optional ci() { 18 | return delegate.ci(); 19 | } 20 | 21 | @Override 22 | public Map ciEnv() { 23 | return delegate.ciEnv(); 24 | } 25 | 26 | @Override 27 | public Optional install() { 28 | return delegate.install(); 29 | } 30 | 31 | @Override 32 | public Map installEnv() { 33 | return delegate.installEnv(); 34 | } 35 | 36 | @Override 37 | public Optional build() { 38 | return delegate.build(); 39 | } 40 | 41 | @Override 42 | public Map buildEnv() { 43 | return delegate.buildEnv(); 44 | } 45 | 46 | @Override 47 | public Optional test() { 48 | return delegate.test(); 49 | } 50 | 51 | @Override 52 | public Map testEnv() { 53 | return delegate.testEnv(); 54 | } 55 | 56 | @Override 57 | public Optional dev() { 58 | return delegate.dev(); 59 | } 60 | 61 | @Override 62 | public Map devEnv() { 63 | return delegate.devEnv(); 64 | } 65 | 66 | @Override 67 | public Optional publish() { 68 | return delegate.publish(); 69 | } 70 | 71 | @Override 72 | public Map publishEnv() { 73 | return delegate.publishEnv(); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /deployment/src/main/java/io/quarkiverse/quinoa/deployment/framework/FrameworkConfigOverrideFactory.java: -------------------------------------------------------------------------------- 1 | package io.quarkiverse.quinoa.deployment.framework; 2 | 3 | import java.nio.file.Path; 4 | import java.util.Optional; 5 | 6 | import jakarta.json.JsonObject; 7 | 8 | import io.quarkiverse.quinoa.deployment.config.QuinoaConfig; 9 | 10 | public interface FrameworkConfigOverrideFactory { 11 | 12 | String getDefaultBuildDir(); 13 | 14 | String getDefaultDevScriptName(); 15 | 16 | QuinoaConfig override(QuinoaConfig delegate, Optional packageJson, Optional detectedDevScript, 17 | boolean isCustomized, Path uiDir); 18 | } -------------------------------------------------------------------------------- /deployment/src/main/java/io/quarkiverse/quinoa/deployment/framework/override/ReactFramework.java: -------------------------------------------------------------------------------- 1 | package io.quarkiverse.quinoa.deployment.framework.override; 2 | 3 | import java.nio.file.Path; 4 | import java.util.HashMap; 5 | import java.util.Map; 6 | import java.util.Optional; 7 | 8 | import jakarta.json.JsonObject; 9 | 10 | import io.quarkiverse.quinoa.deployment.config.PackageManagerCommandConfig; 11 | import io.quarkiverse.quinoa.deployment.config.QuinoaConfig; 12 | import io.quarkiverse.quinoa.deployment.config.delegate.PackageManagerCommandConfigDelegate; 13 | import io.quarkiverse.quinoa.deployment.config.delegate.QuinoaConfigDelegate; 14 | 15 | public class ReactFramework extends GenericFramework { 16 | 17 | public ReactFramework() { 18 | super("build", "start", 3000); 19 | } 20 | 21 | @Override 22 | public QuinoaConfig override(QuinoaConfig delegate, Optional packageJson, Optional detectedDevScript, 23 | boolean isCustomized, Path uiDir) { 24 | return new QuinoaConfigDelegate(super.override(delegate, packageJson, detectedDevScript, isCustomized, uiDir)) { 25 | 26 | @Override 27 | public PackageManagerCommandConfig packageManagerCommand() { 28 | return new PackageManagerCommandConfigDelegate(super.packageManagerCommand()) { 29 | @Override 30 | public Map devEnv() { 31 | // BROWSER=NONE so the browser is not automatically opened with React 32 | Map envs = new HashMap<>(super.testEnv()); 33 | envs.put("BROWSER", "NONE"); 34 | return envs; 35 | } 36 | }; 37 | } 38 | }; 39 | } 40 | } -------------------------------------------------------------------------------- /deployment/src/main/java/io/quarkiverse/quinoa/deployment/items/BuiltResourcesBuildItem.java: -------------------------------------------------------------------------------- 1 | package io.quarkiverse.quinoa.deployment.items; 2 | 3 | import java.nio.file.Path; 4 | import java.util.Optional; 5 | import java.util.Set; 6 | 7 | import io.quarkus.builder.item.SimpleBuildItem; 8 | 9 | public final class BuiltResourcesBuildItem extends SimpleBuildItem { 10 | 11 | private final Optional directory; 12 | private final Set resources; 13 | 14 | public BuiltResourcesBuildItem(Path directory, Set resources) { 15 | this.directory = Optional.ofNullable(directory); 16 | this.resources = resources; 17 | } 18 | 19 | public BuiltResourcesBuildItem(Set entries) { 20 | this.directory = Optional.empty(); 21 | this.resources = entries; 22 | } 23 | 24 | public Optional getDirectory() { 25 | return directory; 26 | } 27 | 28 | public Set resources() { 29 | return resources; 30 | } 31 | 32 | public record BuiltResource(String name, byte[] content) { 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /deployment/src/main/java/io/quarkiverse/quinoa/deployment/items/ConfiguredQuinoaBuildItem.java: -------------------------------------------------------------------------------- 1 | package io.quarkiverse.quinoa.deployment.items; 2 | 3 | import java.nio.file.Path; 4 | 5 | import io.quarkiverse.quinoa.deployment.config.QuinoaConfig; 6 | import io.quarkus.builder.item.SimpleBuildItem; 7 | 8 | public final class ConfiguredQuinoaBuildItem extends SimpleBuildItem { 9 | 10 | private final Path projectDir; 11 | private final Path uiDir; 12 | private final Path packageJson; 13 | private final QuinoaConfig resolvedConfig; 14 | 15 | public ConfiguredQuinoaBuildItem(Path projectDir, Path uiDir, Path packageJson, QuinoaConfig resolvedConfig) { 16 | this.projectDir = projectDir; 17 | this.uiDir = uiDir; 18 | this.packageJson = packageJson; 19 | this.resolvedConfig = resolvedConfig; 20 | } 21 | 22 | public Path projectDir() { 23 | return projectDir; 24 | } 25 | 26 | public Path uiDir() { 27 | return uiDir; 28 | } 29 | 30 | public Path packageJson() { 31 | return packageJson; 32 | } 33 | 34 | public QuinoaConfig resolvedConfig() { 35 | return resolvedConfig; 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /deployment/src/main/java/io/quarkiverse/quinoa/deployment/items/ForwardedDevServerBuildItem.java: -------------------------------------------------------------------------------- 1 | package io.quarkiverse.quinoa.deployment.items; 2 | 3 | import io.quarkiverse.quinoa.QuinoaNetworkConfiguration; 4 | import io.quarkus.builder.item.SimpleBuildItem; 5 | 6 | public final class ForwardedDevServerBuildItem extends SimpleBuildItem { 7 | 8 | private final QuinoaNetworkConfiguration networkConfiguration; 9 | 10 | public ForwardedDevServerBuildItem(QuinoaNetworkConfiguration networkConfiguration) { 11 | this.networkConfiguration = networkConfiguration; 12 | } 13 | 14 | public QuinoaNetworkConfiguration getNetworkConfiguration() { 15 | return networkConfiguration; 16 | } 17 | 18 | public boolean isTls() { 19 | return networkConfiguration.isTls(); 20 | } 21 | 22 | public boolean isTlsAllowInsecure() { 23 | return networkConfiguration.isTlsAllowInsecure(); 24 | } 25 | 26 | public String getHost() { 27 | return networkConfiguration.getHost(); 28 | } 29 | 30 | public Integer getPort() { 31 | return networkConfiguration.getPort(); 32 | } 33 | } -------------------------------------------------------------------------------- /deployment/src/main/java/io/quarkiverse/quinoa/deployment/items/InstalledPackageManagerBuildItem.java: -------------------------------------------------------------------------------- 1 | package io.quarkiverse.quinoa.deployment.items; 2 | 3 | import io.quarkiverse.quinoa.deployment.packagemanager.PackageManagerRunner; 4 | import io.quarkus.builder.item.SimpleBuildItem; 5 | 6 | public final class InstalledPackageManagerBuildItem extends SimpleBuildItem { 7 | 8 | private final PackageManagerRunner packageManagerRunner; 9 | 10 | public InstalledPackageManagerBuildItem(PackageManagerRunner packageManagerRunner) { 11 | this.packageManagerRunner = packageManagerRunner; 12 | } 13 | 14 | public PackageManagerRunner getPackageManager() { 15 | return packageManagerRunner; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /deployment/src/main/java/io/quarkiverse/quinoa/deployment/items/PublishedPackageBuildItem.java: -------------------------------------------------------------------------------- 1 | package io.quarkiverse.quinoa.deployment.items; 2 | 3 | import io.quarkus.builder.item.SimpleBuildItem; 4 | 5 | public final class PublishedPackageBuildItem extends SimpleBuildItem { 6 | 7 | private final boolean skipped; 8 | 9 | public PublishedPackageBuildItem(boolean skipped) { 10 | this.skipped = skipped; 11 | } 12 | 13 | public boolean isSkipped() { 14 | return skipped; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /deployment/src/main/java/io/quarkiverse/quinoa/deployment/items/TargetDirBuildItem.java: -------------------------------------------------------------------------------- 1 | package io.quarkiverse.quinoa.deployment.items; 2 | 3 | import java.nio.file.Path; 4 | 5 | import io.quarkus.builder.item.SimpleBuildItem; 6 | 7 | public final class TargetDirBuildItem extends SimpleBuildItem { 8 | 9 | private final Path buildDirectory; 10 | 11 | public TargetDirBuildItem(Path buildDirectory) { 12 | this.buildDirectory = buildDirectory; 13 | } 14 | 15 | public Path getBuildDirectory() { 16 | return buildDirectory; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /deployment/src/main/java/io/quarkiverse/quinoa/deployment/packagemanager/types/PackageManager.java: -------------------------------------------------------------------------------- 1 | package io.quarkiverse.quinoa.deployment.packagemanager.types; 2 | 3 | import java.util.Collections; 4 | import java.util.List; 5 | import java.util.Map; 6 | 7 | import io.quarkiverse.quinoa.deployment.config.PackageManagerCommandConfig; 8 | import io.quarkus.runtime.LaunchMode; 9 | 10 | public interface PackageManager { 11 | 12 | Command ci(); 13 | 14 | Command install(); 15 | 16 | String binary(); 17 | 18 | Command build(LaunchMode mode); 19 | 20 | Command test(); 21 | 22 | Command publish(); 23 | 24 | Command dev(); 25 | 26 | public static PackageManager resolve(PackageManagerType type, String binary, 27 | PackageManagerCommandConfig packageManagerCommands, 28 | List paths) { 29 | return configure(type, binary, packageManagerCommands, paths); 30 | } 31 | 32 | private static PackageManager configure(PackageManagerType type, String binary, PackageManagerCommandConfig commandsConfig, 33 | List paths) { 34 | return new ConfiguredPackageManager(type, binary, commandsConfig, paths); 35 | } 36 | 37 | class Command { 38 | public final Map envs; 39 | public final String commandWithArguments; 40 | 41 | Command(String commandWithArguments) { 42 | this.envs = Collections.emptyMap(); 43 | this.commandWithArguments = commandWithArguments; 44 | } 45 | 46 | Command(Map envs, String commandWithArguments) { 47 | this.envs = envs; 48 | this.commandWithArguments = commandWithArguments; 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /deployment/src/main/resources/dev-ui/qwc-quinoa-log.js: -------------------------------------------------------------------------------- 1 | import { QwcServerLog} from 'qwc-server-log'; 2 | 3 | /** 4 | * This component filter the log to only show Quinoa related entries. 5 | */ 6 | export class QwcQuinoaLog extends QwcServerLog { 7 | 8 | doLogEntry(entry){ 9 | if (entry.loggerName && entry.loggerName.includes("quinoa")) { 10 | return true; 11 | } 12 | return false; 13 | } 14 | } 15 | 16 | customElements.define('qwc-quinoa-log', QwcQuinoaLog); 17 | -------------------------------------------------------------------------------- /deployment/src/test/empty-webui/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quarkiverse/quarkus-quinoa/0ac98ea681988f670358498f91cb171bb870fd32/deployment/src/test/empty-webui/.gitkeep -------------------------------------------------------------------------------- /deployment/src/test/java/io/quarkiverse/quinoa/deployment/framework/FrameworkTypeTest.java: -------------------------------------------------------------------------------- 1 | package io.quarkiverse.quinoa.deployment.framework; 2 | 3 | import java.io.InputStream; 4 | import java.util.Optional; 5 | 6 | import jakarta.json.Json; 7 | import jakarta.json.JsonObject; 8 | 9 | import org.assertj.core.api.Assertions; 10 | import org.jboss.logging.Logger; 11 | import org.junit.jupiter.params.ParameterizedTest; 12 | import org.junit.jupiter.params.provider.CsvSource; 13 | 14 | public class FrameworkTypeTest { 15 | 16 | private static final Logger LOG = Logger.getLogger(FrameworkTypeTest.class); 17 | 18 | @ParameterizedTest 19 | @CsvSource({ 20 | "react-create-app-exact, REACT, start, false", 21 | "react-create-app-different-dev-script, REACT, dev, true", 22 | "react-create-app-different-dev-script-envs, REACT, dev, true", 23 | "react-create-app-multiple-ok, REACT, start, false", 24 | "react-create-app-multiple-ok-guess, REACT, start, true", 25 | "react-create-app-multiple-ok-guess-command, REACT, develop, true", 26 | "react-create-app-multiple-nok,,,", 27 | "angular-exact, ANGULAR, start, false", 28 | "angular-envs, ANGULAR, start, false", 29 | "angular-args, ANGULAR, start, true", 30 | }) 31 | void testDetection(String jsonResource, String type, String devScript, Boolean customized) { 32 | 33 | ClassLoader classLoader = FrameworkTypeTest.class.getClassLoader(); 34 | 35 | LOG.infof("Testing %s", jsonResource); 36 | 37 | InputStream jsonStream = classLoader.getResourceAsStream("frameworks/" + jsonResource + ".json"); 38 | JsonObject jsonObject = Json.createReader(jsonStream).readObject(); 39 | 40 | Optional result = FrameworkType.detectFramework(jsonObject); 41 | 42 | if (type == null) { 43 | Assertions.assertThat(result).isEmpty(); 44 | } else { 45 | Assertions.assertThat(result) 46 | .isPresent() 47 | .contains(new FrameworkType.DetectedFramework(FrameworkType.valueOf(type), devScript, customized)); 48 | } 49 | 50 | LOG.info("\n"); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /deployment/src/test/java/io/quarkiverse/quinoa/deployment/framework/override/AngularFrameworkTest.java: -------------------------------------------------------------------------------- 1 | package io.quarkiverse.quinoa.deployment.framework.override; 2 | 3 | import static org.assertj.core.api.Assertions.assertThat; 4 | 5 | import java.io.InputStream; 6 | 7 | import jakarta.json.Json; 8 | import jakarta.json.JsonObject; 9 | 10 | import org.junit.jupiter.params.ParameterizedTest; 11 | import org.junit.jupiter.params.provider.CsvSource; 12 | 13 | class AngularFrameworkTest { 14 | 15 | @ParameterizedTest 16 | @CsvSource({ 17 | "builder-browser-output-str, dist/acme-frontend", 18 | "builder-application-output-str, dist/acme-frontend/browser", 19 | "builder-application-output-obj-no-browser, dist/acme-frontend/browser", 20 | "builder-application-output-obj-browser, dist/acme-frontend/ui", 21 | }) 22 | void testBuilderOutputPath(String jsonResource, String expectedBuildDir) { 23 | // given 24 | JsonObject givenBuilder = readTestJson(jsonResource); 25 | 26 | // when 27 | String actual = AngularFramework.getBuildDir(givenBuilder); 28 | 29 | // then 30 | assertThat(actual).isEqualTo(expectedBuildDir); 31 | } 32 | 33 | private JsonObject readTestJson(String jsonResource) { 34 | ClassLoader classLoader = AngularFrameworkTest.class.getClassLoader(); 35 | InputStream jsonStream = classLoader.getResourceAsStream("frameworks/angular/" + jsonResource + ".json"); 36 | return Json.createReader(jsonStream).readObject(); 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /deployment/src/test/java/io/quarkiverse/quinoa/test/QuinoaAbsoluteUIDirTest.java: -------------------------------------------------------------------------------- 1 | package io.quarkiverse.quinoa.test; 2 | 3 | import static io.quarkiverse.quinoa.deployment.testing.QuinoaQuarkusUnitTest.isWindows; 4 | import static io.quarkiverse.quinoa.deployment.testing.QuinoaQuarkusUnitTest.systemBinary; 5 | import static org.assertj.core.api.Assertions.assertThat; 6 | 7 | import java.io.IOException; 8 | import java.nio.file.Files; 9 | import java.nio.file.Path; 10 | 11 | import org.junit.jupiter.api.Test; 12 | import org.junit.jupiter.api.extension.RegisterExtension; 13 | 14 | import io.quarkiverse.quinoa.deployment.testing.QuinoaQuarkusUnitTest; 15 | import io.quarkus.test.QuarkusUnitTest; 16 | 17 | public class QuinoaAbsoluteUIDirTest { 18 | private static final String NAME = "test-webui-absolute-dir"; 19 | 20 | @RegisterExtension 21 | static final QuarkusUnitTest config = QuinoaQuarkusUnitTest.create(getUIDir().resolve("webui")).toQuarkusUnitTest() 22 | .overrideConfigKey("quarkus.package.output-directory", getUIDir().resolve("target").toAbsolutePath().toString()) 23 | .assertLogRecords(l -> { 24 | assertThat(l) 25 | .anyMatch(s -> s.getMessage().equals("Running Quinoa package manager build command: %s") && 26 | s.getParameters()[0].equals(systemBinary("npm") + " run build")); 27 | }); 28 | 29 | static { 30 | try { 31 | Files.createDirectories(getUIDir().resolve("target")); 32 | } catch (IOException e) { 33 | throw new RuntimeException(e); 34 | } 35 | } 36 | 37 | @Test 38 | public void testQuinoa() { 39 | assertThat(getUIDir().resolve(Path.of("target/quinoa/build/index.html"))).isRegularFile() 40 | .hasContent("test"); 41 | assertThat(getUIDir().resolve("webui").resolve("node_modules/installed")).isRegularFile() 42 | .hasContent("hello"); 43 | } 44 | 45 | private static Path getUIDir() { 46 | final Path tmpDir = isWindows() ? Path.of("C:/Temp") : Path.of("/tmp"); 47 | return tmpDir.resolve(NAME); 48 | } 49 | 50 | } 51 | -------------------------------------------------------------------------------- /deployment/src/test/java/io/quarkiverse/quinoa/test/QuinoaAlreadyInstalledTest.java: -------------------------------------------------------------------------------- 1 | package io.quarkiverse.quinoa.test; 2 | 3 | import static io.quarkiverse.quinoa.deployment.testing.QuinoaQuarkusUnitTest.systemBinary; 4 | import static org.assertj.core.api.Assertions.assertThat; 5 | 6 | import org.junit.jupiter.api.Test; 7 | import org.junit.jupiter.api.extension.RegisterExtension; 8 | 9 | import io.quarkiverse.quinoa.deployment.testing.QuinoaQuarkusUnitTest; 10 | import io.quarkus.test.QuarkusUnitTest; 11 | 12 | public class QuinoaAlreadyInstalledTest { 13 | private static final String NAME = "already-installed"; 14 | 15 | @RegisterExtension 16 | static final QuarkusUnitTest config = QuinoaQuarkusUnitTest.create(NAME) 17 | .alreadyInstalled() 18 | .toQuarkusUnitTest() 19 | .assertLogRecords(l -> { 20 | assertThat(l) 21 | .anyMatch(s -> s.getMessage().equals( 22 | "package.json seems to be the same as previous Quinoa install, skipping packages install")) 23 | .noneMatch(s -> s.getMessage().equals("Running Quinoa package manager install command: %s") && 24 | s.getParameters()[0].equals(systemBinary("npm") + " install")); 25 | }).assertException(e -> { 26 | assertThat(e).hasMessage( 27 | "Error in Quinoa while running package manager build command: " + systemBinary("npm") + " run build"); 28 | }); 29 | 30 | @Test 31 | public void testQuinoa() { 32 | // Will assert exception 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /deployment/src/test/java/io/quarkiverse/quinoa/test/QuinoaCIConfigTest.java: -------------------------------------------------------------------------------- 1 | package io.quarkiverse.quinoa.test; 2 | 3 | import static io.quarkiverse.quinoa.deployment.testing.QuinoaQuarkusUnitTest.getWebUITestDirPath; 4 | import static io.quarkiverse.quinoa.deployment.testing.QuinoaQuarkusUnitTest.systemBinary; 5 | import static org.assertj.core.api.Assertions.assertThat; 6 | 7 | import org.junit.jupiter.api.Test; 8 | import org.junit.jupiter.api.extension.RegisterExtension; 9 | 10 | import io.quarkiverse.quinoa.deployment.packagemanager.types.PackageManagerType; 11 | import io.quarkiverse.quinoa.deployment.testing.QuinoaQuarkusUnitTest; 12 | import io.quarkus.test.QuarkusUnitTest; 13 | 14 | public class QuinoaCIConfigTest { 15 | 16 | private static final String NAME = "ci"; 17 | 18 | @RegisterExtension 19 | static final QuarkusUnitTest config = QuinoaQuarkusUnitTest.create(NAME) 20 | .initialLockfile(PackageManagerType.NPM.getLockFile()) 21 | .ci(null) 22 | .toQuarkusUnitTest() 23 | .overrideConfigKey("quarkus.quinoa.ci", "true") 24 | .assertLogRecords(l -> assertThat(l) 25 | .anyMatch(s -> s.getMessage().equals("Running Quinoa package manager ci command: %s") && 26 | s.getParameters()[0].equals( 27 | systemBinary(PackageManagerType.NPM.getBinary()) + " ci"))); 28 | 29 | @Test 30 | public void testQuinoa() { 31 | assertThat(getWebUITestDirPath(NAME).resolve("node_modules/installed")).isRegularFile() 32 | .hasContent("hello"); 33 | } 34 | } -------------------------------------------------------------------------------- /deployment/src/test/java/io/quarkiverse/quinoa/test/QuinoaDefaultConfigTest.java: -------------------------------------------------------------------------------- 1 | package io.quarkiverse.quinoa.test; 2 | 3 | import static io.quarkiverse.quinoa.deployment.testing.QuinoaQuarkusUnitTest.getWebUITestDirPath; 4 | import static io.quarkiverse.quinoa.deployment.testing.QuinoaQuarkusUnitTest.systemBinary; 5 | import static org.assertj.core.api.Assertions.assertThat; 6 | 7 | import java.nio.file.Path; 8 | 9 | import org.junit.jupiter.api.Test; 10 | import org.junit.jupiter.api.extension.RegisterExtension; 11 | 12 | import io.quarkiverse.quinoa.deployment.testing.QuinoaQuarkusUnitTest; 13 | import io.quarkus.test.QuarkusUnitTest; 14 | 15 | public class QuinoaDefaultConfigTest { 16 | 17 | private static final String NAME = "default-config"; 18 | 19 | @RegisterExtension 20 | static final QuarkusUnitTest config = QuinoaQuarkusUnitTest.create(NAME) 21 | .toQuarkusUnitTest() 22 | .assertLogRecords(l -> { 23 | assertThat(l) 24 | .anyMatch(s -> s.getMessage().equals("Running Quinoa package manager build command: %s") && 25 | s.getParameters()[0].equals(systemBinary("npm") + " run build")); 26 | }); 27 | 28 | @Test 29 | public void testQuinoa() { 30 | assertThat(Path.of("target/quinoa/build/index.html")).isRegularFile() 31 | .hasContent("test"); 32 | assertThat(getWebUITestDirPath(NAME).resolve("node_modules/installed")).isRegularFile() 33 | .hasContent("hello"); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /deployment/src/test/java/io/quarkiverse/quinoa/test/QuinoaForceInstallTest.java: -------------------------------------------------------------------------------- 1 | package io.quarkiverse.quinoa.test; 2 | 3 | import static io.quarkiverse.quinoa.deployment.testing.QuinoaQuarkusUnitTest.getWebUITestDirPath; 4 | import static io.quarkiverse.quinoa.deployment.testing.QuinoaQuarkusUnitTest.systemBinary; 5 | import static org.assertj.core.api.Assertions.assertThat; 6 | 7 | import java.nio.file.Path; 8 | 9 | import org.junit.jupiter.api.Test; 10 | import org.junit.jupiter.api.extension.RegisterExtension; 11 | 12 | import io.quarkiverse.quinoa.deployment.testing.QuinoaQuarkusUnitTest; 13 | import io.quarkus.test.QuarkusUnitTest; 14 | 15 | public class QuinoaForceInstallTest { 16 | private static final String NAME = "force-install"; 17 | 18 | @RegisterExtension 19 | static final QuarkusUnitTest config = QuinoaQuarkusUnitTest.create(NAME) 20 | .alreadyInstalled() 21 | .toQuarkusUnitTest() 22 | .overrideConfigKey("quarkus.quinoa.force-install", "true") 23 | .assertLogRecords(l -> { 24 | assertThat(l) 25 | .anyMatch(s -> s.getMessage().equals("Running Quinoa package manager install command: %s") && 26 | s.getParameters()[0].equals(systemBinary("npm") + " install")); 27 | assertThat(l) 28 | .anyMatch(s -> s.getMessage().equals("Running Quinoa package manager build command: %s") && 29 | s.getParameters()[0].equals(systemBinary("npm") + " run build")); 30 | }); 31 | 32 | @Test 33 | public void testQuinoa() { 34 | assertThat(Path.of("target/quinoa/build/index.html")).isRegularFile() 35 | .hasContent("test"); 36 | assertThat(getWebUITestDirPath(NAME).resolve("node_modules/installed")).isRegularFile() 37 | .hasContent("hello"); 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /deployment/src/test/java/io/quarkiverse/quinoa/test/QuinoaIgnorePathPrefixesConfigTest.java: -------------------------------------------------------------------------------- 1 | package io.quarkiverse.quinoa.test; 2 | 3 | import static org.assertj.core.api.Assertions.assertThat; 4 | 5 | import org.junit.jupiter.api.Test; 6 | import org.junit.jupiter.api.extension.RegisterExtension; 7 | 8 | import io.quarkiverse.quinoa.deployment.testing.QuinoaQuarkusUnitTest; 9 | import io.quarkus.test.QuarkusUnitTest; 10 | 11 | public class QuinoaIgnorePathPrefixesConfigTest { 12 | private static final String NAME = "ignore-path-prefixes"; 13 | 14 | @RegisterExtension 15 | static final QuarkusUnitTest config = QuinoaQuarkusUnitTest.create(NAME).toQuarkusUnitTest() 16 | .overrideConfigKey("quarkus.quinoa.ignored-path-prefixes", "/foo/bar,/api,q,a/b") 17 | .overrideConfigKey("quarkus.quinoa.enable-spa-routing", "true") 18 | .assertLogRecords(l -> assertThat(l) 19 | .anyMatch(s -> s.getMessage() 20 | .equals("Quinoa SPA routing handler is ignoring paths starting with: /foo/bar, /api, /q, /a/b"))); 21 | 22 | @Test 23 | public void testQuinoa() { 24 | // Will assert log records 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /deployment/src/test/java/io/quarkiverse/quinoa/test/QuinoaInvalidBuildDirTest.java: -------------------------------------------------------------------------------- 1 | package io.quarkiverse.quinoa.test; 2 | 3 | import static org.assertj.core.api.Assertions.assertThat; 4 | 5 | import org.junit.jupiter.api.Test; 6 | import org.junit.jupiter.api.extension.RegisterExtension; 7 | 8 | import io.quarkiverse.quinoa.deployment.testing.QuinoaQuarkusUnitTest; 9 | import io.quarkus.runtime.configuration.ConfigurationException; 10 | import io.quarkus.test.QuarkusUnitTest; 11 | 12 | public class QuinoaInvalidBuildDirTest { 13 | private static final String NAME = "invalid-build-dir"; 14 | 15 | @RegisterExtension 16 | static final QuarkusUnitTest config = QuinoaQuarkusUnitTest.create(NAME).toQuarkusUnitTest() 17 | .overrideConfigKey("quarkus.quinoa.build-dir", "dist") 18 | .assertException(t -> { 19 | assertThat(t.getMessage()).startsWith("Quinoa build directory not found: '"); 20 | assertThat(t.getMessage()).endsWith("dist'"); 21 | assertThat((ConfigurationException) t).satisfies(e -> { 22 | assertThat(e.getConfigKeys()).containsExactly("quarkus.quinoa.build-dir"); 23 | }); 24 | }); 25 | 26 | @Test 27 | public void testQuinoaError() { 28 | // Will asset log records 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /deployment/src/test/java/io/quarkiverse/quinoa/test/QuinoaNoDirTest.java: -------------------------------------------------------------------------------- 1 | package io.quarkiverse.quinoa.test; 2 | 3 | import static org.assertj.core.api.Assertions.assertThat; 4 | 5 | import org.junit.jupiter.api.Test; 6 | import org.junit.jupiter.api.extension.RegisterExtension; 7 | 8 | import io.quarkiverse.quinoa.deployment.testing.QuinoaQuarkusUnitTest; 9 | import io.quarkus.test.QuarkusUnitTest; 10 | 11 | public class QuinoaNoDirTest { 12 | private static final String NAME = "no-webui-dir"; 13 | 14 | @RegisterExtension 15 | static final QuarkusUnitTest config = QuinoaQuarkusUnitTest.create(NAME).toQuarkusUnitTest() 16 | .overrideConfigKey("quarkus.quinoa.ui-dir", "src/test/no-webui") 17 | .assertLogRecords(l -> assertThat(l).anyMatch(s -> s.getMessage().equals( 18 | "Quinoa directory not found 'quarkus.quinoa.ui-dir=%s' resolved to '%s'. It is recommended to remove the quarkus-quinoa extension if not used.") 19 | && 20 | s.getParameters()[0].equals("src/test/no-webui"))); 21 | 22 | @Test 23 | public void testQuinoaError() { 24 | // Will assert log records 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /deployment/src/test/java/io/quarkiverse/quinoa/test/QuinoaNoPackageJsonTest.java: -------------------------------------------------------------------------------- 1 | package io.quarkiverse.quinoa.test; 2 | 3 | import static org.assertj.core.api.Assertions.assertThat; 4 | 5 | import org.junit.jupiter.api.Test; 6 | import org.junit.jupiter.api.extension.RegisterExtension; 7 | 8 | import io.quarkiverse.quinoa.deployment.testing.QuinoaQuarkusUnitTest; 9 | import io.quarkus.test.QuarkusUnitTest; 10 | 11 | public class QuinoaNoPackageJsonTest { 12 | private static final String NAME = "no-package-json"; 13 | 14 | @RegisterExtension 15 | static final QuarkusUnitTest config = QuinoaQuarkusUnitTest.create(NAME).toQuarkusUnitTest() 16 | .overrideConfigKey("quarkus.quinoa.ui-dir", "src/test/empty-webui") 17 | .assertException(e -> { 18 | assertThat(e).hasMessage("No package.json found in Web UI directory: 'src/test/empty-webui'"); 19 | }); 20 | 21 | @Test 22 | public void testQuinoaError() { 23 | // Will asset log records 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /deployment/src/test/java/io/quarkiverse/quinoa/test/QuinoaPackageManagerInstallCommandOverrideTest.java: -------------------------------------------------------------------------------- 1 | package io.quarkiverse.quinoa.test; 2 | 3 | import static io.quarkiverse.quinoa.deployment.testing.QuinoaQuarkusUnitTest.getWebUITestDirPath; 4 | import static io.quarkiverse.quinoa.test.QuinoaPackageManagerInstallTest.computeBinary; 5 | import static org.assertj.core.api.Assertions.assertThat; 6 | 7 | import java.nio.file.Path; 8 | 9 | import org.junit.jupiter.api.Test; 10 | import org.junit.jupiter.api.extension.RegisterExtension; 11 | 12 | import io.quarkiverse.quinoa.deployment.testing.QuinoaQuarkusUnitTest; 13 | import io.quarkus.test.QuarkusUnitTest; 14 | 15 | public class QuinoaPackageManagerInstallCommandOverrideTest { 16 | private static final String NAME = "package-manager-install-command-override"; 17 | public static final String INSTALL_DIR = "target/node-" + NAME; 18 | 19 | @RegisterExtension 20 | static final QuarkusUnitTest config = QuinoaQuarkusUnitTest.create(NAME).toQuarkusUnitTest() 21 | .overrideConfigKey("quarkus.quinoa.package-manager-install", "true") 22 | .overrideConfigKey("quarkus.quinoa.package-manager-install.node-version", "20.10.0") 23 | .overrideConfigKey("quarkus.quinoa.package-manager-install.install-dir", INSTALL_DIR) 24 | .overrideConfigKey("quarkus.quinoa.package-manager-command.build", "run build-something") 25 | .overrideConfigKey("quarkus.quinoa.package-manager-command.build-env.BUILD", "yeahhh") 26 | .assertLogRecords(l -> assertThat(l) 27 | .anyMatch(s -> s.getMessage().equals("Running Quinoa package manager build command: %s") && 28 | ((String) s.getParameters()[0]) 29 | .endsWith(computeBinary(INSTALL_DIR) 30 | + " run build-something"))); 31 | 32 | @Test 33 | public void testQuinoa() { 34 | assertThat(Path.of("target/quinoa/build/index.html")).isRegularFile() 35 | .hasContent("yeahhh"); 36 | assertThat(getWebUITestDirPath(NAME).resolve("node_modules/installed")).isRegularFile() 37 | .hasContent("hello"); 38 | assertThat(Path.of(INSTALL_DIR)).isDirectory(); 39 | assertThat(Path.of(INSTALL_DIR + "/node")).isDirectory(); 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /deployment/src/test/java/io/quarkiverse/quinoa/test/QuinoaPackageManagerInstallTest.java: -------------------------------------------------------------------------------- 1 | package io.quarkiverse.quinoa.test; 2 | 3 | import static io.quarkiverse.quinoa.deployment.packagemanager.PackageManagerInstall.NODE_BINARY; 4 | import static io.quarkiverse.quinoa.deployment.packagemanager.PackageManagerInstall.NPM_PATH; 5 | import static io.quarkiverse.quinoa.deployment.packagemanager.PackageManagerInstall.normalizePath; 6 | import static io.quarkiverse.quinoa.deployment.packagemanager.PackageManagerInstall.quotePathWithSpaces; 7 | import static io.quarkiverse.quinoa.deployment.testing.QuinoaQuarkusUnitTest.getWebUITestDirPath; 8 | import static org.assertj.core.api.Assertions.assertThat; 9 | 10 | import java.nio.file.Path; 11 | 12 | import org.junit.jupiter.api.Test; 13 | import org.junit.jupiter.api.extension.RegisterExtension; 14 | 15 | import io.quarkiverse.quinoa.deployment.testing.QuinoaQuarkusUnitTest; 16 | import io.quarkus.test.QuarkusUnitTest; 17 | 18 | public class QuinoaPackageManagerInstallTest { 19 | private static final String NAME = "package-manager-install"; 20 | public static final String INSTALL_DIR = "target/node-" + NAME; 21 | 22 | @RegisterExtension 23 | static final QuarkusUnitTest config = QuinoaQuarkusUnitTest.create(NAME).toQuarkusUnitTest() 24 | .overrideConfigKey("quarkus.quinoa.package-manager-install", "true") 25 | .overrideConfigKey("quarkus.quinoa.package-manager-install.node-version", "20.10.0") 26 | .overrideConfigKey("quarkus.quinoa.package-manager-install.install-dir", INSTALL_DIR) 27 | .assertLogRecords(l -> { 28 | assertThat(l) 29 | .anyMatch(s -> s.getMessage().equals("Running Quinoa package manager build command: %s") && 30 | ((String) s.getParameters()[0]) 31 | .endsWith(computeBinary(INSTALL_DIR) + " run build")); 32 | assertThat(l) 33 | .anyMatch(s -> s.getMessage().equals("v20.10.0")); 34 | }); 35 | 36 | @Test 37 | public void testQuinoa() { 38 | assertThat(Path.of("target/quinoa/build/index.html")).isRegularFile() 39 | .hasContent("test"); 40 | assertThat(getWebUITestDirPath(NAME).resolve("node_modules/installed")).isRegularFile() 41 | .hasContent("hello"); 42 | assertThat(Path.of(INSTALL_DIR)).isDirectory(); 43 | assertThat(Path.of(INSTALL_DIR + "/node")).isDirectory(); 44 | } 45 | 46 | static String computeBinary(String installDir) { 47 | return NODE_BINARY + " " 48 | + quotePathWithSpaces(normalizePath( 49 | Path.of(installDir, NPM_PATH).toAbsolutePath().toString())); 50 | } 51 | 52 | } 53 | -------------------------------------------------------------------------------- /deployment/src/test/java/io/quarkiverse/quinoa/test/QuinoaPackageManagerInstallWithSpaceTest.java: -------------------------------------------------------------------------------- 1 | package io.quarkiverse.quinoa.test; 2 | 3 | import static io.quarkiverse.quinoa.deployment.testing.QuinoaQuarkusUnitTest.getWebUITestDirPath; 4 | import static io.quarkiverse.quinoa.test.QuinoaPackageManagerInstallTest.computeBinary; 5 | import static org.assertj.core.api.Assertions.assertThat; 6 | 7 | import java.nio.file.Path; 8 | 9 | import org.junit.jupiter.api.Test; 10 | import org.junit.jupiter.api.extension.RegisterExtension; 11 | 12 | import io.quarkiverse.quinoa.deployment.testing.QuinoaQuarkusUnitTest; 13 | import io.quarkus.test.QuarkusUnitTest; 14 | 15 | public class QuinoaPackageManagerInstallWithSpaceTest { 16 | private static final String NAME = "package-manager-install"; 17 | private static final String INSTALL_DIR = "target/node-space- " + NAME; 18 | 19 | @RegisterExtension 20 | static final QuarkusUnitTest config = QuinoaQuarkusUnitTest.create(NAME).toQuarkusUnitTest() 21 | .overrideConfigKey("quarkus.quinoa.package-manager-install", "true") 22 | .overrideConfigKey("quarkus.quinoa.package-manager-install.node-version", "20.10.0") 23 | .overrideConfigKey("quarkus.quinoa.package-manager-install.install-dir", INSTALL_DIR) 24 | .assertLogRecords(l -> { 25 | assertThat(l) 26 | .anyMatch(s -> s.getMessage().equals("Running Quinoa package manager build command: %s") && 27 | ((String) s.getParameters()[0]) 28 | .endsWith(computeBinary(INSTALL_DIR) + " run build")); 29 | assertThat(l) 30 | .anyMatch(s -> s.getMessage().equals("v20.10.0")); 31 | }); 32 | 33 | @Test 34 | public void testQuinoa() { 35 | assertThat(Path.of("target/quinoa/build/index.html")).isRegularFile() 36 | .hasContent("test"); 37 | assertThat(getWebUITestDirPath(NAME).resolve("node_modules/installed")).isRegularFile() 38 | .hasContent("hello"); 39 | assertThat(Path.of(INSTALL_DIR)).isDirectory(); 40 | assertThat(Path.of(INSTALL_DIR + "/node")).isDirectory(); 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /deployment/src/test/java/io/quarkiverse/quinoa/test/QuinoaPackageManagerLockfileDetectNPMTest.java: -------------------------------------------------------------------------------- 1 | package io.quarkiverse.quinoa.test; 2 | 3 | import static io.quarkiverse.quinoa.deployment.testing.QuinoaQuarkusUnitTest.getWebUITestDirPath; 4 | import static io.quarkiverse.quinoa.deployment.testing.QuinoaQuarkusUnitTest.systemBinary; 5 | import static org.assertj.core.api.Assertions.assertThat; 6 | 7 | import java.nio.file.Path; 8 | 9 | import org.junit.jupiter.api.Test; 10 | import org.junit.jupiter.api.extension.RegisterExtension; 11 | 12 | import io.quarkiverse.quinoa.deployment.packagemanager.types.PackageManagerType; 13 | import io.quarkiverse.quinoa.deployment.testing.QuinoaQuarkusUnitTest; 14 | import io.quarkus.test.QuarkusUnitTest; 15 | 16 | public class QuinoaPackageManagerLockfileDetectNPMTest { 17 | private static final String NAME = "package-manager-lockfile-detect-npm"; 18 | 19 | @RegisterExtension 20 | static final QuarkusUnitTest config = QuinoaQuarkusUnitTest.create(NAME) 21 | .initialLockfile(PackageManagerType.NPM.getLockFile()) 22 | .toQuarkusUnitTest() 23 | .assertLogRecords(l -> assertThat(l) 24 | .anyMatch(s -> s.getMessage().equals("Running Quinoa package manager build command: %s") && 25 | s.getParameters()[0].equals(systemBinary(PackageManagerType.NPM.getBinary()) + " run build"))); 26 | 27 | @Test 28 | public void testQuinoa() { 29 | assertThat(Path.of("target/quinoa/build/index.html")).isRegularFile() 30 | .hasContent("test"); 31 | assertThat(getWebUITestDirPath(NAME).resolve("node_modules/installed")).isRegularFile() 32 | .hasContent("hello"); 33 | } 34 | 35 | } -------------------------------------------------------------------------------- /deployment/src/test/java/io/quarkiverse/quinoa/test/QuinoaPackageManagerLockfileDetectPNPMTest.java: -------------------------------------------------------------------------------- 1 | package io.quarkiverse.quinoa.test; 2 | 3 | import static io.quarkiverse.quinoa.deployment.testing.QuinoaQuarkusUnitTest.getWebUITestDirPath; 4 | import static io.quarkiverse.quinoa.deployment.testing.QuinoaQuarkusUnitTest.systemBinary; 5 | import static org.assertj.core.api.Assertions.assertThat; 6 | 7 | import java.nio.file.Path; 8 | 9 | import org.junit.jupiter.api.Test; 10 | import org.junit.jupiter.api.extension.RegisterExtension; 11 | 12 | import io.quarkiverse.quinoa.deployment.packagemanager.types.PackageManagerType; 13 | import io.quarkiverse.quinoa.deployment.testing.QuinoaQuarkusUnitTest; 14 | import io.quarkus.test.QuarkusUnitTest; 15 | 16 | public class QuinoaPackageManagerLockfileDetectPNPMTest { 17 | private static final String NAME = "package-manager-lockfile-detect-pnpm"; 18 | 19 | @RegisterExtension 20 | static final QuarkusUnitTest config = QuinoaQuarkusUnitTest.create(NAME) 21 | .initialLockfile(PackageManagerType.PNPM.getLockFile()) 22 | .toQuarkusUnitTest() 23 | .assertLogRecords(l -> assertThat(l) 24 | .anyMatch(s -> s.getMessage().equals("Running Quinoa package manager build command: %s") && 25 | s.getParameters()[0].equals(systemBinary(PackageManagerType.PNPM.getBinary()) + " run build"))); 26 | 27 | @Test 28 | public void testQuinoa() { 29 | assertThat(Path.of("target/quinoa/build/index.html")).isRegularFile() 30 | .hasContent("test"); 31 | assertThat(getWebUITestDirPath(NAME).resolve("node_modules/installed")).isRegularFile() 32 | .hasContent("hello"); 33 | } 34 | 35 | } -------------------------------------------------------------------------------- /deployment/src/test/java/io/quarkiverse/quinoa/test/QuinoaPackageManagerLockfileDetectYarnTest.java: -------------------------------------------------------------------------------- 1 | package io.quarkiverse.quinoa.test; 2 | 3 | import static io.quarkiverse.quinoa.deployment.testing.QuinoaQuarkusUnitTest.getWebUITestDirPath; 4 | import static io.quarkiverse.quinoa.deployment.testing.QuinoaQuarkusUnitTest.systemBinary; 5 | import static org.assertj.core.api.Assertions.assertThat; 6 | 7 | import java.nio.file.Path; 8 | 9 | import org.junit.jupiter.api.Test; 10 | import org.junit.jupiter.api.extension.RegisterExtension; 11 | 12 | import io.quarkiverse.quinoa.deployment.packagemanager.types.PackageManagerType; 13 | import io.quarkiverse.quinoa.deployment.testing.QuinoaQuarkusUnitTest; 14 | import io.quarkus.test.QuarkusUnitTest; 15 | 16 | public class QuinoaPackageManagerLockfileDetectYarnTest { 17 | private static final String NAME = "package-manager-lockfile-detect-yarn"; 18 | 19 | @RegisterExtension 20 | static final QuarkusUnitTest config = QuinoaQuarkusUnitTest.create(NAME) 21 | .initialLockfile(PackageManagerType.YARN.getLockFile()) 22 | .toQuarkusUnitTest() 23 | .assertLogRecords(l -> { 24 | assertThat(l).anyMatch(s -> s.getMessage().equals("Running Quinoa package manager build command: %s") && 25 | s.getParameters()[0].equals(systemBinary(PackageManagerType.YARN.getBinary()) + " run build")); 26 | }); 27 | 28 | @Test 29 | public void testQuinoa() { 30 | assertThat(Path.of("target/quinoa/build/index.html")).isRegularFile() 31 | .hasContent("test"); 32 | assertThat(getWebUITestDirPath(NAME).resolve("node_modules/installed")).isRegularFile() 33 | .hasContent("hello"); 34 | } 35 | 36 | } -------------------------------------------------------------------------------- /deployment/src/test/java/io/quarkiverse/quinoa/test/QuinoaPackageManagerNPMOverrideBuildEnvTest.java: -------------------------------------------------------------------------------- 1 | package io.quarkiverse.quinoa.test; 2 | 3 | import static io.quarkiverse.quinoa.deployment.testing.QuinoaQuarkusUnitTest.getWebUITestDirPath; 4 | import static io.quarkiverse.quinoa.deployment.testing.QuinoaQuarkusUnitTest.systemBinary; 5 | import static org.assertj.core.api.Assertions.assertThat; 6 | 7 | import java.nio.file.Path; 8 | 9 | import org.junit.jupiter.api.Test; 10 | import org.junit.jupiter.api.extension.RegisterExtension; 11 | 12 | import io.quarkiverse.quinoa.deployment.testing.QuinoaQuarkusUnitTest; 13 | import io.quarkus.test.QuarkusUnitTest; 14 | 15 | public class QuinoaPackageManagerNPMOverrideBuildEnvTest { 16 | private static final String NAME = "package-manager-npm-override-build"; 17 | private static final String BUILD_COMMAND = "run build-something"; 18 | 19 | @RegisterExtension 20 | static final QuarkusUnitTest config = QuinoaQuarkusUnitTest.create(NAME).toQuarkusUnitTest() 21 | .overrideConfigKey("quarkus.quinoa.package-manager-command.build", BUILD_COMMAND) 22 | .overrideConfigKey("quarkus.quinoa.package-manager-command.build-env.BUILD", "develop") 23 | .assertLogRecords(l -> assertThat(l) 24 | .anyMatch(s -> s.getMessage().equals("Running Quinoa package manager build command: %s") && 25 | s.getParameters()[0].equals(systemBinary("npm") + " " + BUILD_COMMAND))); 26 | 27 | @Test 28 | public void testQuinoa() { 29 | assertThat(Path.of("target/quinoa/build/index.html")).isRegularFile() 30 | .hasContent("develop"); 31 | assertThat(getWebUITestDirPath(NAME).resolve("node_modules/installed")).isRegularFile() 32 | .hasContent("hello"); 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /deployment/src/test/java/io/quarkiverse/quinoa/test/QuinoaPackageManagerNPMOverrideEnvTest.java: -------------------------------------------------------------------------------- 1 | package io.quarkiverse.quinoa.test; 2 | 3 | import static io.quarkiverse.quinoa.deployment.testing.QuinoaQuarkusUnitTest.getWebUITestDirPath; 4 | import static io.quarkiverse.quinoa.deployment.testing.QuinoaQuarkusUnitTest.systemBinary; 5 | import static org.assertj.core.api.Assertions.assertThat; 6 | 7 | import java.nio.file.Path; 8 | 9 | import org.junit.jupiter.api.Test; 10 | import org.junit.jupiter.api.extension.RegisterExtension; 11 | 12 | import io.quarkiverse.quinoa.deployment.testing.QuinoaQuarkusUnitTest; 13 | import io.quarkus.test.QuarkusUnitTest; 14 | 15 | public class QuinoaPackageManagerNPMOverrideEnvTest { 16 | private static final String NAME = "package-manager-npm-override-env"; 17 | private static final String MODE = "develop"; 18 | 19 | @RegisterExtension 20 | static final QuarkusUnitTest config = QuinoaQuarkusUnitTest.create(NAME).toQuarkusUnitTest() 21 | .overrideConfigKey("quarkus.quinoa.package-manager-command.build-env.MODE", MODE) 22 | .assertLogRecords(l -> assertThat(l) 23 | .anyMatch(s -> s.getMessage().equals("Running Quinoa package manager build command: %s") && 24 | s.getParameters()[0].equals(systemBinary("npm") + " run build"))); 25 | 26 | @Test 27 | public void testQuinoa() { 28 | assertThat(Path.of("target/quinoa/build/index.html")).isRegularFile() 29 | .hasContent(MODE); 30 | assertThat(getWebUITestDirPath(NAME).resolve("node_modules/installed")).isRegularFile() 31 | .hasContent("hello"); 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /deployment/src/test/java/io/quarkiverse/quinoa/test/QuinoaPackageManagerPublishTest.java: -------------------------------------------------------------------------------- 1 | package io.quarkiverse.quinoa.test; 2 | 3 | import static io.quarkiverse.quinoa.deployment.testing.QuinoaQuarkusUnitTest.getWebUITestDirPath; 4 | import static org.assertj.core.api.Assertions.assertThat; 5 | 6 | import org.junit.jupiter.api.Test; 7 | import org.junit.jupiter.api.extension.RegisterExtension; 8 | 9 | import io.quarkiverse.quinoa.deployment.testing.QuinoaQuarkusUnitTest; 10 | import io.quarkus.test.QuarkusUnitTest; 11 | 12 | public class QuinoaPackageManagerPublishTest { 13 | private static final String NAME = "package-manager-publish"; 14 | 15 | @RegisterExtension 16 | static final QuarkusUnitTest config = QuinoaQuarkusUnitTest.create(NAME).toQuarkusUnitTest() 17 | .overrideConfigKey("quarkus.quinoa.just-build", "true") 18 | .overrideConfigKey("quarkus.quinoa.publish", "true") 19 | .assertLogRecords(l -> { 20 | assertThat(l) 21 | .anyMatch(s -> s.getMessage().startsWith("Running Quinoa package manager publish command")); 22 | }); 23 | 24 | @Test 25 | public void testQuinoa() { 26 | // target/quinoa/build dir shall not exist while just-build activated 27 | assertThat(getWebUITestDirPath(NAME).resolve("quinoa-app-1.0.0.tgz")).exists(); 28 | assertThat(getWebUITestDirPath(NAME).resolve("node_modules/installed")).isRegularFile() 29 | .hasContent("hello"); 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /deployment/src/test/java/io/quarkiverse/quinoa/test/QuinoaPackageManagerSetYarnConfigTest.java: -------------------------------------------------------------------------------- 1 | package io.quarkiverse.quinoa.test; 2 | 3 | import static io.quarkiverse.quinoa.deployment.testing.QuinoaQuarkusUnitTest.getWebUITestDirPath; 4 | import static io.quarkiverse.quinoa.deployment.testing.QuinoaQuarkusUnitTest.systemBinary; 5 | import static org.assertj.core.api.Assertions.assertThat; 6 | 7 | import java.nio.file.Path; 8 | 9 | import org.junit.jupiter.api.Test; 10 | import org.junit.jupiter.api.extension.RegisterExtension; 11 | 12 | import io.quarkiverse.quinoa.deployment.testing.QuinoaQuarkusUnitTest; 13 | import io.quarkus.test.QuarkusUnitTest; 14 | 15 | public class QuinoaPackageManagerSetYarnConfigTest { 16 | private static final String NAME = "package-manager-set-yarn"; 17 | 18 | @RegisterExtension 19 | static final QuarkusUnitTest config = QuinoaQuarkusUnitTest.create(NAME).toQuarkusUnitTest() 20 | .overrideConfigKey("quarkus.quinoa.package-manager", systemBinary("yarn")) 21 | .overrideConfigKey("quarkus.quinoa.frozen-lockfile", "false") 22 | .assertLogRecords(l -> assertThat(l) 23 | .anyMatch(s -> s.getMessage().equals("Running Quinoa package manager build command: %s") && 24 | s.getParameters()[0].equals(systemBinary("yarn") + " run build"))); 25 | 26 | @Test 27 | public void testQuinoa() { 28 | assertThat(Path.of("target/quinoa/build/index.html")).isRegularFile() 29 | .hasContent("test"); 30 | assertThat(getWebUITestDirPath(NAME).resolve("node_modules/installed")).isRegularFile() 31 | .hasContent("hello"); 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /deployment/src/test/java/io/quarkiverse/quinoa/test/QuinoaPackageManagerSetYarnOtherConfigTest.java: -------------------------------------------------------------------------------- 1 | package io.quarkiverse.quinoa.test; 2 | 3 | import static org.assertj.core.api.Assertions.assertThat; 4 | 5 | import org.junit.jupiter.api.Test; 6 | import org.junit.jupiter.api.extension.RegisterExtension; 7 | 8 | import io.quarkiverse.quinoa.deployment.packagemanager.types.PackageManagerType; 9 | import io.quarkiverse.quinoa.deployment.testing.QuinoaQuarkusUnitTest; 10 | import io.quarkus.test.QuarkusUnitTest; 11 | 12 | public class QuinoaPackageManagerSetYarnOtherConfigTest { 13 | private static final String NAME = "package-manager-set-yarn-other"; 14 | 15 | @RegisterExtension 16 | static final QuarkusUnitTest config = QuinoaQuarkusUnitTest.create(NAME) 17 | .initialLockfile(PackageManagerType.YARN.getLockFile()) 18 | .toQuarkusUnitTest() 19 | .overrideConfigKey("quarkus.quinoa.package-manager", "yarn.binary") 20 | .assertException(e -> { 21 | assertThat(e).hasMessage("Error in Quinoa while running package manager install command: yarn.binary install"); 22 | }); 23 | 24 | @Test 25 | public void testQuinoa() { 26 | // test logs 27 | } 28 | 29 | } -------------------------------------------------------------------------------- /deployment/src/test/java/io/quarkiverse/quinoa/test/QuinoaPathPrefixesRESTConfigRelativeRootPathTest.java: -------------------------------------------------------------------------------- 1 | package io.quarkiverse.quinoa.test; 2 | 3 | import static io.quarkiverse.quinoa.deployment.testing.QuinoaQuarkusUnitTest.getWebUITestDirPath; 4 | import static org.assertj.core.api.Assertions.assertThat; 5 | 6 | import java.nio.file.Path; 7 | 8 | import org.junit.jupiter.api.Test; 9 | import org.junit.jupiter.api.extension.RegisterExtension; 10 | 11 | import io.quarkiverse.quinoa.deployment.testing.QuinoaQuarkusUnitTest; 12 | import io.quarkus.test.QuarkusUnitTest; 13 | 14 | public class QuinoaPathPrefixesRESTConfigRelativeRootPathTest { 15 | 16 | private static final String NAME = "resteasy-reactive-path-config-relative-root-path"; 17 | 18 | @RegisterExtension 19 | static final QuarkusUnitTest config = QuinoaQuarkusUnitTest.create(NAME) 20 | .toQuarkusUnitTest() 21 | .overrideConfigKey("quarkus.http.root-path", "root/path") 22 | .overrideConfigKey("quarkus.rest.path", "foo/reactive") 23 | .overrideConfigKey("quarkus.resteasy.path", "foo/classic") 24 | .overrideConfigKey("quarkus.http.non-application-root-path", "bar/non") 25 | .overrideConfigKey("quarkus.quinoa.enable-spa-routing", "true") 26 | .assertLogRecords(l -> assertThat(l) 27 | .anyMatch(s -> s.getMessage() 28 | // note how /bar/non is part of the ignored paths 29 | // this is because bar/non is relative to the root path when it does not start with a slash 30 | // also note that quarkus.rest.path, and quarkus.resteasy.path are always relative to the root path even if they start with a slash 31 | .equals("Quinoa SPA routing handler is ignoring paths starting with: /foo/classic, /foo/reactive, /bar/non")) 32 | .anyMatch(s -> s.getMessage() 33 | .equals("Quinoa is available at: /root/path/"))); 34 | 35 | @Test 36 | public void testQuinoa() { 37 | assertThat(Path.of("target/quinoa/build/index.html")).isRegularFile() 38 | .hasContent("test"); 39 | assertThat(getWebUITestDirPath(NAME).resolve("node_modules/installed")).isRegularFile() 40 | .hasContent("hello"); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /deployment/src/test/java/io/quarkiverse/quinoa/test/QuinoaPathPrefixesRESTConfigRootPathTest.java: -------------------------------------------------------------------------------- 1 | package io.quarkiverse.quinoa.test; 2 | 3 | import static io.quarkiverse.quinoa.deployment.testing.QuinoaQuarkusUnitTest.getWebUITestDirPath; 4 | import static org.assertj.core.api.Assertions.assertThat; 5 | 6 | import java.nio.file.Path; 7 | 8 | import org.junit.jupiter.api.Test; 9 | import org.junit.jupiter.api.extension.RegisterExtension; 10 | 11 | import io.quarkiverse.quinoa.deployment.testing.QuinoaQuarkusUnitTest; 12 | import io.quarkus.test.QuarkusUnitTest; 13 | 14 | public class QuinoaPathPrefixesRESTConfigRootPathTest { 15 | 16 | private static final String NAME = "resteasy-reactive-path-config-root-path"; 17 | 18 | @RegisterExtension 19 | static final QuarkusUnitTest config = QuinoaQuarkusUnitTest.create(NAME) 20 | .toQuarkusUnitTest() 21 | .overrideConfigKey("quarkus.http.root-path", "/root/path") 22 | .overrideConfigKey("quarkus.rest.path", "/foo/reactive") 23 | .overrideConfigKey("quarkus.resteasy.path", "/foo/classic") 24 | .overrideConfigKey("quarkus.http.non-application-root-path", "/bar/non") 25 | .overrideConfigKey("quarkus.quinoa.enable-spa-routing", "true") 26 | .assertLogRecords(l -> assertThat(l) 27 | .anyMatch(s -> s.getMessage() 28 | // note how /bar/non is not part of the ignored paths 29 | // this is because /bar/non is not relative to /root/path 30 | // also note that quarkus.rest.path, and quarkus.resteasy.path are always relative to the root path even if they start with a slash 31 | .equals("Quinoa SPA routing handler is ignoring paths starting with: /foo/classic, /foo/reactive")) 32 | .anyMatch(s -> s.getMessage() 33 | .equals("Quinoa is available at: /root/path/"))); 34 | 35 | @Test 36 | public void testQuinoa() { 37 | assertThat(Path.of("target/quinoa/build/index.html")).isRegularFile() 38 | .hasContent("test"); 39 | assertThat(getWebUITestDirPath(NAME).resolve("node_modules/installed")).isRegularFile() 40 | .hasContent("hello"); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /deployment/src/test/java/io/quarkiverse/quinoa/test/QuinoaPathPrefixesRESTConfigTest.java: -------------------------------------------------------------------------------- 1 | package io.quarkiverse.quinoa.test; 2 | 3 | import static io.quarkiverse.quinoa.deployment.testing.QuinoaQuarkusUnitTest.getWebUITestDirPath; 4 | import static org.assertj.core.api.Assertions.assertThat; 5 | 6 | import java.nio.file.Path; 7 | 8 | import org.junit.jupiter.api.Test; 9 | import org.junit.jupiter.api.extension.RegisterExtension; 10 | 11 | import io.quarkiverse.quinoa.deployment.testing.QuinoaQuarkusUnitTest; 12 | import io.quarkus.test.QuarkusUnitTest; 13 | 14 | public class QuinoaPathPrefixesRESTConfigTest { 15 | 16 | private static final String NAME = "resteasy-reactive-path-config"; 17 | 18 | @RegisterExtension 19 | static final QuarkusUnitTest config = QuinoaQuarkusUnitTest.create(NAME) 20 | .toQuarkusUnitTest() 21 | .overrideConfigKey("quarkus.rest.path", "/foo/reactive") 22 | .overrideConfigKey("quarkus.resteasy.path", "/foo/classic") 23 | .overrideConfigKey("quarkus.http.non-application-root-path", "/bar/non") 24 | .overrideConfigKey("quarkus.quinoa.enable-spa-routing", "true") 25 | .assertLogRecords(l -> assertThat(l) 26 | .anyMatch(s -> s.getMessage() 27 | .equals("Quinoa SPA routing handler is ignoring paths starting with: /foo/classic, /foo/reactive, /bar/non")) 28 | .anyMatch(s -> s.getMessage() 29 | .equals("Quinoa is available at: /"))); 30 | 31 | @Test 32 | public void testQuinoa() { 33 | assertThat(Path.of("target/quinoa/build/index.html")).isRegularFile() 34 | .hasContent("test"); 35 | assertThat(getWebUITestDirPath(NAME).resolve("node_modules/installed")).isRegularFile() 36 | .hasContent("hello"); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /deployment/src/test/java/io/quarkiverse/quinoa/test/QuinoaPathPrefixesRESTConfigUiRootPathTest.java: -------------------------------------------------------------------------------- 1 | package io.quarkiverse.quinoa.test; 2 | 3 | import static io.quarkiverse.quinoa.deployment.testing.QuinoaQuarkusUnitTest.getWebUITestDirPath; 4 | import static org.assertj.core.api.Assertions.assertThat; 5 | 6 | import java.nio.file.Path; 7 | 8 | import org.junit.jupiter.api.Test; 9 | import org.junit.jupiter.api.extension.RegisterExtension; 10 | 11 | import io.quarkiverse.quinoa.deployment.testing.QuinoaQuarkusUnitTest; 12 | import io.quarkus.test.QuarkusUnitTest; 13 | 14 | public class QuinoaPathPrefixesRESTConfigUiRootPathTest { 15 | 16 | private static final String NAME = "resteasy-reactive-path-config-ui-root-path"; 17 | 18 | @RegisterExtension 19 | static final QuarkusUnitTest config = QuinoaQuarkusUnitTest.create(NAME) 20 | .toQuarkusUnitTest() 21 | .overrideConfigKey("quarkus.http.root-path", "/root/path") 22 | .overrideConfigKey("quarkus.quinoa.ui-root-path", "/foo") 23 | .overrideConfigKey("quarkus.rest.path", "/foo/reactive") 24 | .overrideConfigKey("quarkus.resteasy.path", "/foo/classic") 25 | .overrideConfigKey("quarkus.http.non-application-root-path", "/bar/non") 26 | .overrideConfigKey("quarkus.quinoa.enable-spa-routing", "true") 27 | .assertLogRecords(l -> assertThat(l) 28 | .anyMatch(s -> s.getMessage() 29 | // ignored paths are always relative to the ui root path 30 | .equals("Quinoa SPA routing handler is ignoring paths starting with: /classic, /reactive")) 31 | .anyMatch(s -> s.getMessage() 32 | .equals("Quinoa is available at: /root/path/foo/"))); 33 | 34 | @Test 35 | public void testQuinoa() { 36 | assertThat(Path.of("target/quinoa/build/index.html")).isRegularFile() 37 | .hasContent("test"); 38 | assertThat(getWebUITestDirPath(NAME).resolve("node_modules/installed")).isRegularFile() 39 | .hasContent("hello"); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /deployment/src/test/java/io/quarkiverse/quinoa/test/devmode/ClassicDevModeCompressionTest.java: -------------------------------------------------------------------------------- 1 | package io.quarkiverse.quinoa.test.devmode; 2 | 3 | import static org.hamcrest.Matchers.containsString; 4 | import static org.hamcrest.Matchers.is; 5 | 6 | import org.hamcrest.Matchers; 7 | import org.jboss.shrinkwrap.api.asset.StringAsset; 8 | import org.junit.jupiter.api.Test; 9 | import org.junit.jupiter.api.extension.RegisterExtension; 10 | 11 | import io.quarkus.test.QuarkusDevModeTest; 12 | import io.restassured.RestAssured; 13 | 14 | public class ClassicDevModeCompressionTest { 15 | @RegisterExtension 16 | final static QuarkusDevModeTest test = new QuarkusDevModeTest() 17 | .withApplicationRoot((jar) -> jar 18 | .add(new StringAsset( 19 | "quarkus.quinoa=true\n" + 20 | "quarkus.quinoa.ui-dir=src/main/webui\n" + 21 | "quarkus.http.enable-compression=true"), 22 | "application.properties")) 23 | .setCodeGenSources("webui"); 24 | 25 | @Test 26 | public void testWebUI() { 27 | RestAssured.when().get("/").then() 28 | .statusCode(200) 29 | .header("Content-Encoding", "gzip") 30 | .body(containsString("dev")); 31 | RestAssured.when().get("/some-page.html").then() 32 | .statusCode(200) 33 | .header("Content-Encoding", "gzip") 34 | .body(is("Hello Quinoa")); 35 | RestAssured.when().get("/some-image.svg").then() 36 | .statusCode(200) 37 | .header("Content-Encoding", Matchers.nullValue()) 38 | .body(is("svg")); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /deployment/src/test/java/io/quarkiverse/quinoa/test/devmode/ClassicDevModeTest.java: -------------------------------------------------------------------------------- 1 | package io.quarkiverse.quinoa.test.devmode; 2 | 3 | import static org.hamcrest.Matchers.containsString; 4 | import static org.hamcrest.Matchers.is; 5 | 6 | import org.hamcrest.Matchers; 7 | import org.jboss.shrinkwrap.api.asset.StringAsset; 8 | import org.junit.jupiter.api.Test; 9 | import org.junit.jupiter.api.extension.RegisterExtension; 10 | 11 | import io.quarkus.test.QuarkusDevModeTest; 12 | import io.restassured.RestAssured; 13 | 14 | public class ClassicDevModeTest { 15 | @RegisterExtension 16 | final static QuarkusDevModeTest test = new QuarkusDevModeTest() 17 | .withApplicationRoot((jar) -> jar 18 | .add(new StringAsset( 19 | "quarkus.quinoa=true\n" + 20 | "quarkus.quinoa.ui-dir=src/main/webui\n"), 21 | "application.properties")) 22 | .setCodeGenSources("webui"); 23 | 24 | @Test 25 | public void testWebUI() { 26 | RestAssured.when().get("/").then() 27 | .statusCode(200) 28 | .header("Content-Encoding", Matchers.nullValue()) 29 | .body(containsString("dev")); 30 | RestAssured.when().get("/some-page.html").then() 31 | .statusCode(200) 32 | .body(is("Hello Quinoa")); 33 | test.modifyFile("webui/public/some-page.html", s -> s.replace("Quinoa", "Quinoa with DevMode")); 34 | RestAssured.when().get("/some-page.html").then() 35 | .statusCode(200) 36 | .body(is("Hello Quinoa with DevMode")); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /deployment/src/test/java/io/quarkiverse/quinoa/test/devmode/ForwardedDevModeCompressionTest.java: -------------------------------------------------------------------------------- 1 | package io.quarkiverse.quinoa.test.devmode; 2 | 3 | import static org.hamcrest.Matchers.containsString; 4 | 5 | import org.hamcrest.Matchers; 6 | import org.jboss.shrinkwrap.api.asset.StringAsset; 7 | import org.junit.jupiter.api.Test; 8 | import org.junit.jupiter.api.extension.RegisterExtension; 9 | 10 | import io.quarkus.test.QuarkusDevModeTest; 11 | import io.restassured.RestAssured; 12 | 13 | public class ForwardedDevModeCompressionTest { 14 | @RegisterExtension 15 | final static QuarkusDevModeTest test = new QuarkusDevModeTest() 16 | .withApplicationRoot((jar) -> jar 17 | .add(new StringAsset( 18 | "quarkus.quinoa=true\n" + 19 | "quarkus.quinoa.ui-dir=src/main/webui\n" + 20 | "quarkus.quinoa.dev-server.port=3000\n" + 21 | "quarkus.http.enable-compression=true"), 22 | "application.properties")) 23 | .setCodeGenSources("webui"); 24 | 25 | @Test 26 | public void testWebUI() { 27 | RestAssured.when().get("/").then() 28 | .statusCode(200) 29 | .header("Content-Encoding", "gzip") 30 | .body(containsString("live-coding")); 31 | RestAssured.when().get("/some-file.js").then() 32 | .statusCode(200) 33 | .header("Content-Encoding", "gzip") 34 | .body(containsString("live-coding")); 35 | RestAssured.when().get("/some-file.svg").then() 36 | .statusCode(200) 37 | .header("Content-Encoding", Matchers.nullValue()) 38 | .body(containsString("live-coding")); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /deployment/src/test/java/io/quarkiverse/quinoa/test/devmode/ForwardedDevModeTest.java: -------------------------------------------------------------------------------- 1 | package io.quarkiverse.quinoa.test.devmode; 2 | 3 | import static io.restassured.RestAssured.given; 4 | import static org.hamcrest.Matchers.containsString; 5 | 6 | import org.hamcrest.Matchers; 7 | import org.jboss.shrinkwrap.api.asset.StringAsset; 8 | import org.junit.jupiter.api.Test; 9 | import org.junit.jupiter.api.extension.RegisterExtension; 10 | 11 | import io.quarkus.test.QuarkusDevModeTest; 12 | import io.restassured.RestAssured; 13 | import io.restassured.http.ContentType; 14 | 15 | public class ForwardedDevModeTest { 16 | @RegisterExtension 17 | final static QuarkusDevModeTest test = new QuarkusDevModeTest() 18 | .withApplicationRoot((jar) -> jar 19 | .add(new StringAsset( 20 | "quarkus.quinoa=true\n" + 21 | "quarkus.quinoa.ui-dir=src/main/webui\n" + 22 | "quarkus.quinoa.dev-server.port=3000\n"), 23 | "application.properties")) 24 | .setCodeGenSources("webui"); 25 | 26 | @Test 27 | public void testWebUI() { 28 | RestAssured.when().get("/").then() 29 | .statusCode(200) 30 | .header("Content-Encoding", Matchers.nullValue()) 31 | .body(containsString("live-coding")); 32 | given() 33 | .body("{}") 34 | .contentType(ContentType.JSON) 35 | .when().post("/api/something").then() 36 | .statusCode(405); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /deployment/src/test/resources/application.properties: -------------------------------------------------------------------------------- 1 | quarkus.log.category."io.quarkiverse.quinoa".level=DEBUG -------------------------------------------------------------------------------- /deployment/src/test/resources/frameworks/angular-args.json: -------------------------------------------------------------------------------- 1 | { 2 | "scripts": { 3 | "start": "ng serve --hmr" 4 | } 5 | } -------------------------------------------------------------------------------- /deployment/src/test/resources/frameworks/angular-envs.json: -------------------------------------------------------------------------------- 1 | { 2 | "scripts": { 3 | "start": "FOO=BAR ng serve" 4 | } 5 | } -------------------------------------------------------------------------------- /deployment/src/test/resources/frameworks/angular-exact.json: -------------------------------------------------------------------------------- 1 | { 2 | "scripts": { 3 | "start": "ng serve" 4 | } 5 | } -------------------------------------------------------------------------------- /deployment/src/test/resources/frameworks/angular/builder-application-output-obj-browser.json: -------------------------------------------------------------------------------- 1 | { 2 | "builder": "@angular-devkit/build-angular:application", 3 | "options": { 4 | "outputPath": { 5 | "base": "dist/acme-frontend", 6 | "browser": "ui" 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /deployment/src/test/resources/frameworks/angular/builder-application-output-obj-no-browser.json: -------------------------------------------------------------------------------- 1 | { 2 | "builder": "@angular-devkit/build-angular:application", 3 | "options": { 4 | "outputPath": { 5 | "base": "dist/acme-frontend" 6 | } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /deployment/src/test/resources/frameworks/angular/builder-application-output-str.json: -------------------------------------------------------------------------------- 1 | { 2 | "builder": "@angular-devkit/build-angular:application", 3 | "options": { 4 | "outputPath": "dist/acme-frontend" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /deployment/src/test/resources/frameworks/angular/builder-browser-output-str.json: -------------------------------------------------------------------------------- 1 | { 2 | "builder": "@angular-devkit/build-angular:browser", 3 | "options": { 4 | "outputPath": "dist/acme-frontend" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /deployment/src/test/resources/frameworks/react-create-app-different-dev-script-envs.json: -------------------------------------------------------------------------------- 1 | { 2 | "scripts": { 3 | "dev": "FOO=BAR react-scripts start", 4 | "build": "react-scripts build", 5 | "test": "react-scripts test", 6 | "eject": "react-scripts eject" 7 | } 8 | } -------------------------------------------------------------------------------- /deployment/src/test/resources/frameworks/react-create-app-different-dev-script.json: -------------------------------------------------------------------------------- 1 | { 2 | "scripts": { 3 | "dev": "react-scripts start", 4 | "build": "react-scripts build", 5 | "test": "react-scripts test", 6 | "eject": "react-scripts eject" 7 | } 8 | } -------------------------------------------------------------------------------- /deployment/src/test/resources/frameworks/react-create-app-exact.json: -------------------------------------------------------------------------------- 1 | { 2 | "scripts": { 3 | "start": "react-scripts start", 4 | "build": "react-scripts build", 5 | "test": "react-scripts test", 6 | "eject": "react-scripts eject" 7 | } 8 | } -------------------------------------------------------------------------------- /deployment/src/test/resources/frameworks/react-create-app-multiple-nok.json: -------------------------------------------------------------------------------- 1 | { 2 | "scripts": { 3 | "develop": "react-scripts start --something-else", 4 | "dev": "react-scripts start --something" 5 | } 6 | } -------------------------------------------------------------------------------- /deployment/src/test/resources/frameworks/react-create-app-multiple-ok-guess-command.json: -------------------------------------------------------------------------------- 1 | { 2 | "scripts": { 3 | "develop": "react-scripts start", 4 | "dev": "react-scripts start --something" 5 | } 6 | } -------------------------------------------------------------------------------- /deployment/src/test/resources/frameworks/react-create-app-multiple-ok-guess.json: -------------------------------------------------------------------------------- 1 | { 2 | "scripts": { 3 | "start": "react-scripts start --something-else", 4 | "dev": "react-scripts start --something" 5 | } 6 | } -------------------------------------------------------------------------------- /deployment/src/test/resources/frameworks/react-create-app-multiple-ok.json: -------------------------------------------------------------------------------- 1 | { 2 | "scripts": { 3 | "start": "react-scripts start", 4 | "dev": "react-scripts start --something" 5 | } 6 | } -------------------------------------------------------------------------------- /deployment/src/test/webui/.gitignore: -------------------------------------------------------------------------------- 1 | package-lock.json 2 | pnpm-lock.json 3 | yarn.lock -------------------------------------------------------------------------------- /deployment/src/test/webui/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "quinoa-app", 3 | "version": "1.0.0", 4 | "private": true, 5 | "scripts": { 6 | "test": "echo \"Error: no test specified\" && exit 1", 7 | "node-version": "node -v", 8 | "build": "npm run node-version && mkdirp build && cross-env-shell \"echo $MODE>build/index.html\" && copyfiles -u 1 public/* build/", 9 | "build-something": "mkdirp build && cross-env-shell \"echo $BUILD>build/index.html\" && copyfiles -u 1 public/* build/", 10 | "start": "cross-env MODE=live-coding npm run build && node server.js", 11 | "postinstall": "echo hello> node_modules/installed", 12 | "publish": "npm pack" 13 | }, 14 | "keywords": [], 15 | "author": "", 16 | "license": "MIT", 17 | "dependencies": { 18 | "lodash": "^4.17.21" 19 | }, 20 | "devDependencies": { 21 | "cross-env": "7.0.3", 22 | "copyfiles": "2.4.1", 23 | "mkdirp": "1.0.4" 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /deployment/src/test/webui/public/some-image.svg: -------------------------------------------------------------------------------- 1 | svg -------------------------------------------------------------------------------- /deployment/src/test/webui/public/some-page.html: -------------------------------------------------------------------------------- 1 | Hello Quinoa -------------------------------------------------------------------------------- /deployment/src/test/webui/server.js: -------------------------------------------------------------------------------- 1 | var fs = require('fs'), 2 | http = require('http'); 3 | 4 | http.createServer(function (req, res) { 5 | fs.readFile(__dirname + "/build/index.html", function (err,data) { 6 | if (err) { 7 | res.writeHead(404); 8 | res.end(JSON.stringify(err)); 9 | return; 10 | } 11 | res.writeHead(200); 12 | res.end(data); 13 | }); 14 | }).listen(3000); -------------------------------------------------------------------------------- /docs/antora.yml: -------------------------------------------------------------------------------- 1 | name: quarkus-quinoa 2 | title: Quinoa 3 | version: dev 4 | nav: 5 | - modules/ROOT/nav.adoc 6 | -------------------------------------------------------------------------------- /docs/modules/ROOT/assets/images/npm-logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /docs/modules/ROOT/assets/images/plus-sign.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 19 | 21 | 28 | 29 | 46 | 48 | 49 | 51 | image/svg+xml 52 | 54 | 55 | 56 | 57 | 61 | 65 | 66 | 67 | -------------------------------------------------------------------------------- /docs/modules/ROOT/assets/images/quarkus.svg: -------------------------------------------------------------------------------- 1 | quarkus_icon_rgb_1024px_reverse -------------------------------------------------------------------------------- /docs/modules/ROOT/assets/images/quinoa-build.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quarkiverse/quarkus-quinoa/0ac98ea681988f670358498f91cb171bb870fd32/docs/modules/ROOT/assets/images/quinoa-build.png -------------------------------------------------------------------------------- /docs/modules/ROOT/assets/images/quinoa-proxy-dev.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quarkiverse/quarkus-quinoa/0ac98ea681988f670358498f91cb171bb870fd32/docs/modules/ROOT/assets/images/quinoa-proxy-dev.png -------------------------------------------------------------------------------- /docs/modules/ROOT/assets/images/quinoa-runtime-prod.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quarkiverse/quarkus-quinoa/0ac98ea681988f670358498f91cb171bb870fd32/docs/modules/ROOT/assets/images/quinoa-runtime-prod.png -------------------------------------------------------------------------------- /docs/modules/ROOT/nav.adoc: -------------------------------------------------------------------------------- 1 | include::./includes/attributes.adoc[] 2 | :config-file: application.properties 3 | 4 | * xref:index.adoc[Getting started] 5 | * xref:main-concepts.adoc[Main Concepts] 6 | * xref:web-frameworks.adoc[Web Frameworks] 7 | * xref:advanced-guides.adoc[Advanced Guides] 8 | * xref:testing.adoc[Testing] 9 | * xref:config-reference.adoc[Config Reference] 10 | -------------------------------------------------------------------------------- /docs/modules/ROOT/pages/config-reference.adoc: -------------------------------------------------------------------------------- 1 | = Quarkus Quinoa - Configuration Reference 2 | 3 | include::./includes/attributes.adoc[] 4 | 5 | include::includes/quarkus-quinoa.adoc[leveloffset=+1, opts=optional] 6 | -------------------------------------------------------------------------------- /docs/modules/ROOT/pages/includes/attributes.adoc: -------------------------------------------------------------------------------- 1 | :quarkus-version: 3.15.1 2 | :quarkus-quinoa-version: 2.5.4 3 | :maven-version: 3.8.1+ 4 | :extension-status: stable 5 | 6 | :quarkus-org-url: https://github.com/quarkusio 7 | :quarkus-base-url: {quarkus-org-url}/quarkus 8 | :quarkus-clone-url: {quarkus-base-url}.git 9 | :quarkus-archive-url: {quarkus-base-url}/archive/master.zip 10 | :quarkus-tree-url: {quarkus-base-url}/tree/main 11 | :quarkus-issues-url: {quarkus-base-url}/issues 12 | :quarkus-guides-url: https://quarkus.io/guides 13 | :quickstarts-base-url: https://github.com/quarkusio/quarkus-quickstarts 14 | :quickstarts-clone-url: https://github.com/quarkusio/quarkus-quickstarts.git 15 | :quickstarts-archive-url: https://github.com/quarkusio/quarkus-quickstarts/archive/main.zip 16 | :quickstarts-blob-url: https://github.com/quarkusio/quarkus-quickstarts/blob/main 17 | :quickstarts-tree-url: https://github.com/quarkusio/quarkus-quickstarts/tree/main -------------------------------------------------------------------------------- /docs/modules/ROOT/pages/main-concepts.adoc: -------------------------------------------------------------------------------- 1 | = Quarkus Quinoa - Main Concepts 2 | 3 | include::./includes/attributes.adoc[] 4 | 5 | == How it works 6 | 7 | === The Quinoa build (using npm) 8 | 9 | image::quinoa-build.png[Quinoa Build] 10 | 11 | NOTE: packages are installed by Quinoa before the build when needed (i.e `npm install`). See xref:advanced-guides.adoc#install-packages[Packages installation]. Quinoa is pre-configured to work with your favorite xref:advanced-guides.adoc#package-manager[package manager] (npm, yarn or pnpm). 12 | 13 | === Runtime for production mode 14 | 15 | When running jar or binary in production mode: 16 | 17 | image::quinoa-runtime-prod.png[Quinoa Runtime Production] 18 | 19 | === Runtime for full Quarkus live-coding 20 | 21 | Quinoa (using Quarkus live-coding watch feature) will watch the Web UI directory and trigger a new build on changes. It works the same as the production mode. This option is perfect for small/fast builds. 22 | 23 | NOTE: You can differentiate the build for xref:advanced-guides.adoc#build-mode[dev mode]. e.g to disable minification. 24 | 25 | [#how-dev-server] 26 | === Runtime for proxied live-coding 27 | 28 | When running dev-mode (e.g with npm on port 3000): 29 | 30 | image::quinoa-proxy-dev.png[Quinoa Proxy Dev] 31 | 32 | NOTE: Quarkus live-coding will keep watching for the backend changes as usual. 33 | 34 | See xref:advanced-guides.adoc#dev-server[Enable the proxied live coding]. 35 | -------------------------------------------------------------------------------- /docs/templates/includes/attributes.adoc: -------------------------------------------------------------------------------- 1 | :quarkus-version: ${quarkus.version} 2 | :quarkus-quinoa-version: ${release.current-version} 3 | :maven-version: 3.8.1+ 4 | :extension-status: stable 5 | 6 | :quarkus-org-url: https://github.com/quarkusio 7 | :quarkus-base-url: {quarkus-org-url}/quarkus 8 | :quarkus-clone-url: {quarkus-base-url}.git 9 | :quarkus-archive-url: {quarkus-base-url}/archive/master.zip 10 | :quarkus-tree-url: {quarkus-base-url}/tree/main 11 | :quarkus-issues-url: {quarkus-base-url}/issues 12 | :quarkus-guides-url: https://quarkus.io/guides 13 | :quickstarts-base-url: https://github.com/quarkusio/quarkus-quickstarts 14 | :quickstarts-clone-url: https://github.com/quarkusio/quarkus-quickstarts.git 15 | :quickstarts-archive-url: https://github.com/quarkusio/quarkus-quickstarts/archive/main.zip 16 | :quickstarts-blob-url: https://github.com/quarkusio/quarkus-quickstarts/blob/main 17 | :quickstarts-tree-url: https://github.com/quarkusio/quarkus-quickstarts/tree/main -------------------------------------------------------------------------------- /integration-tests/src/main/java/io/quarkiverse/quinoa/it/QuinoaResource.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package io.quarkiverse.quinoa.it; 18 | 19 | import jakarta.enterprise.context.ApplicationScoped; 20 | import jakarta.ws.rs.Consumes; 21 | import jakarta.ws.rs.DELETE; 22 | import jakarta.ws.rs.GET; 23 | import jakarta.ws.rs.POST; 24 | import jakarta.ws.rs.PUT; 25 | import jakarta.ws.rs.Path; 26 | import jakarta.ws.rs.Produces; 27 | import jakarta.ws.rs.core.MediaType; 28 | 29 | @Path("/api/quinoa") 30 | @ApplicationScoped 31 | public class QuinoaResource { 32 | // add some rest methods here 33 | 34 | @GET 35 | @Produces(MediaType.TEXT_PLAIN) 36 | public String hello() { 37 | return "Hello Quinoa"; 38 | } 39 | 40 | @POST 41 | @Consumes(MediaType.TEXT_PLAIN) 42 | @Produces(MediaType.TEXT_PLAIN) 43 | public String hello(String message) { 44 | return "Hello Quinoa " + message; 45 | } 46 | 47 | @PUT 48 | @Consumes(MediaType.TEXT_PLAIN) 49 | @Produces(MediaType.TEXT_PLAIN) 50 | public String update(String message) { 51 | return "Quinoa updated with: " + message; 52 | } 53 | 54 | @DELETE 55 | @Produces(MediaType.TEXT_PLAIN) 56 | public String delete() { 57 | return "Quinoa deleted successfully!"; 58 | } 59 | } -------------------------------------------------------------------------------- /integration-tests/src/main/resources/META-INF/resources/index.html: -------------------------------------------------------------------------------- 1 | NOT QUINOA -------------------------------------------------------------------------------- /integration-tests/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | %lit-root-path,lit-ui-root-path.quarkus.http.root-path=/foo/bar 2 | %lit-root-path,lit-ui-root-path.quarkus.quinoa.enable-spa-routing=true 3 | %lit-root-path,lit-ui-root-path.quarkus.quinoa.package-manager-command.build-env.API_PATH=/foo/bar/api/ 4 | 5 | %lit-root-path.quarkus.quinoa.package-manager-command.build-env.ROOT_PATH=/foo/bar 6 | 7 | %lit-ui-root-path.quarkus.quinoa.ui-root-path=/ui 8 | %lit-ui-root-path.quarkus.quinoa.package-manager-command.build-env.ROOT_PATH=/foo/bar/ui 9 | %lit-ui-root-path.quarkus.quinoa.ignored-path-prefixes=/ignored 10 | 11 | quarkus.quinoa.ui-dir=src/main/ui-react 12 | %react.quarkus.quinoa.ui-dir=src/main/ui-react 13 | %vue.quarkus.quinoa.ui-dir=src/main/ui-vue 14 | %angular.quarkus.quinoa.ui-dir=src/main/ui-angular 15 | %angular.quarkus.quinoa.enable-spa-routing=true 16 | %angular.quarkus.rest.path=/bar/foo 17 | %angular.quarkus.quinoa.ignored-path-prefixes=/q,/bar/foo/baz 18 | %angular.quarkus.quinoa.package-manager-install=true 19 | %angular.quarkus.quinoa.package-manager-install.install-dir=target/ 20 | %angular.quarkus.quinoa.package-manager-install.node-version=22.14.0 21 | %angular.quarkus.quinoa.package-manager-install.yarn-version=1.22.19 22 | 23 | %angular-esbuild.quarkus.quinoa.ui-dir=src/main/ui-angular-esbuild 24 | %angular-esbuild.quarkus.quinoa.enable-spa-routing=true 25 | %angular-esbuild.quarkus.rest.path=/bar/foo 26 | %angular-esbuild.quarkus.quinoa.ignored-path-prefixes=/q,/bar/foo/baz 27 | %angular-esbuild.quarkus.quinoa.package-manager-install=true 28 | %angular-esbuild.quarkus.quinoa.package-manager-install.install-dir=target/ 29 | %angular-esbuild.quarkus.quinoa.package-manager-install.node-version=22.14.0 30 | 31 | %lit,lit-root-path,lit-ui-root-path.quarkus.quinoa.ui-dir=src/main/ui-lit 32 | %lit,lit-root-path,lit-ui-root-path.quarkus.quinoa.build-dir=dist 33 | %lit,lit-root-path,lit-ui-root-path.quarkus.http.static-resources.index-page=app.html 34 | %lit,lit-root-path,lit-ui-root-path.quarkus.quinoa.package-manager-command.build=run build-per-env 35 | %lit-root-path,lit-ui-root-path.quarkus.quinoa.package-manager-command.build-env.FOO=bar 36 | %lit.quarkus.quinoa.package-manager-command.build-env.FOO=bar 37 | %lit.quarkus.quinoa.package-manager-command.build-env.ROOT_PATH=/ 38 | %lit.quarkus.quinoa.package-manager-command.build-env.API_PATH=/api/ 39 | 40 | %yarn.quarkus.quinoa.package-manager=yarn 41 | %just-build.quarkus.quinoa.just-build=true -------------------------------------------------------------------------------- /integration-tests/src/main/ui-angular-esbuild/.gitignore: -------------------------------------------------------------------------------- 1 | /build/ 2 | /benchpress-build/ 3 | .DS_Store 4 | gen_docs.disable 5 | test.disable 6 | regression/temp*.html 7 | performance/temp*.html 8 | .idea/workspace.xml 9 | *~ 10 | *.swp 11 | .angular 12 | angular.js.tmproj 13 | node_modules/ 14 | angular.xcodeproj 15 | .firebase/ 16 | .idea 17 | 18 | .yarn/* 19 | !.yarn/patches 20 | !.yarn/plugins 21 | !.yarn/releases 22 | !.yarn/sdks 23 | !.yarn/versions 24 | 25 | *.iml 26 | .agignore 27 | .lvimrc 28 | libpeerconnection.log 29 | npm-debug.log 30 | /tmp/ 31 | .vscode 32 | *.log 33 | *.stackdump 34 | scripts/code.angularjs.org-firebase/deploy 35 | scripts/docs.angularjs.org-firebase/deploy 36 | scripts/docs.angularjs.org-firebase/functions/content 37 | Terms 38 | Privacy 39 | Security 40 | Status 41 | Docs 42 | Contact GitHub 43 | Pricing 44 | API 45 | Training 46 | Blog 47 | About 48 | -------------------------------------------------------------------------------- /integration-tests/src/main/ui-angular-esbuild/README.md: -------------------------------------------------------------------------------- 1 | # QuinoaApp 2 | 3 | This project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 18.0.5. 4 | 5 | ## Development server 6 | 7 | Run `ng serve` for a dev server. Navigate to `http://localhost:4200/`. The application will automatically reload if you change any of the source files. 8 | 9 | ## Code scaffolding 10 | 11 | Run `ng generate component component-name` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module`. 12 | 13 | ## Build 14 | 15 | Run `ng build` to build the project. The build artifacts will be stored in the `dist/` directory. 16 | 17 | ## Running unit tests 18 | 19 | Run `ng test` to execute the unit tests via [Karma](https://karma-runner.github.io). 20 | 21 | ## Running end-to-end tests 22 | 23 | Run `ng e2e` to execute the end-to-end tests via a platform of your choice. To use this command, you need to first add a package that implements end-to-end testing capabilities. 24 | 25 | ## Further help 26 | 27 | To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI Overview and Command Reference](https://angular.dev/tools/cli) page. 28 | -------------------------------------------------------------------------------- /integration-tests/src/main/ui-angular-esbuild/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "quinoa", 3 | "version": "0.0.0", 4 | "scripts": { 5 | "ng": "ng", 6 | "start": "ng serve", 7 | "build": "ng build", 8 | "watch": "ng build --watch --configuration development", 9 | "test": "ng test" 10 | }, 11 | "private": true, 12 | "dependencies": { 13 | "@angular/animations": "^19.2.6", 14 | "@angular/common": "^19.2.6", 15 | "@angular/compiler": "^19.2.6", 16 | "@angular/core": "^19.2.6", 17 | "@angular/forms": "^19.2.6", 18 | "@angular/platform-browser": "^19.2.6", 19 | "@angular/platform-browser-dynamic": "^19.2.6", 20 | "@angular/router": "^19.2.6", 21 | "rxjs": "~7.8.0", 22 | "tslib": "^2.3.0", 23 | "zone.js": "~0.15.0" 24 | }, 25 | "devDependencies": { 26 | "@angular-devkit/build-angular": "^19.2.7", 27 | "@angular/cli": "^19.2.7", 28 | "@angular/compiler-cli": "^19.2.6", 29 | "@types/jasmine": "~5.1.0", 30 | "jasmine-core": "~5.1.0", 31 | "karma": "~6.4.0", 32 | "karma-chrome-launcher": "~3.2.0", 33 | "karma-coverage": "~2.2.0", 34 | "karma-jasmine": "~5.1.0", 35 | "karma-jasmine-html-reporter": "~2.1.0", 36 | "typescript": "~5.8.3" 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /integration-tests/src/main/ui-angular-esbuild/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quarkiverse/quarkus-quinoa/0ac98ea681988f670358498f91cb171bb870fd32/integration-tests/src/main/ui-angular-esbuild/public/favicon.ico -------------------------------------------------------------------------------- /integration-tests/src/main/ui-angular-esbuild/src/app/app.component.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quarkiverse/quarkus-quinoa/0ac98ea681988f670358498f91cb171bb870fd32/integration-tests/src/main/ui-angular-esbuild/src/app/app.component.css -------------------------------------------------------------------------------- /integration-tests/src/main/ui-angular-esbuild/src/app/app.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { TestBed } from '@angular/core/testing'; 2 | import { AppComponent } from './app.component'; 3 | 4 | describe('AppComponent', () => { 5 | beforeEach(async () => { 6 | await TestBed.configureTestingModule({ 7 | imports: [AppComponent], 8 | }).compileComponents(); 9 | }); 10 | 11 | it('should create the app', () => { 12 | const fixture = TestBed.createComponent(AppComponent); 13 | const app = fixture.componentInstance; 14 | expect(app).toBeTruthy(); 15 | }); 16 | 17 | it(`should have the 'quinoa-app' title`, () => { 18 | const fixture = TestBed.createComponent(AppComponent); 19 | const app = fixture.componentInstance; 20 | expect(app.title).toEqual('quinoa-app'); 21 | }); 22 | 23 | it('should render title', () => { 24 | const fixture = TestBed.createComponent(AppComponent); 25 | fixture.detectChanges(); 26 | const compiled = fixture.nativeElement as HTMLElement; 27 | expect(compiled.querySelector('h1')?.textContent).toContain('Hello, quinoa-app'); 28 | }); 29 | }); 30 | -------------------------------------------------------------------------------- /integration-tests/src/main/ui-angular-esbuild/src/app/app.component.ts: -------------------------------------------------------------------------------- 1 | import { AsyncPipe } from "@angular/common"; 2 | import { HttpClient } from "@angular/common/http"; 3 | import { Component, inject } from "@angular/core"; 4 | import { RouterOutlet } from "@angular/router"; 5 | import { Observable } from "rxjs"; 6 | 7 | @Component({ 8 | selector: "app-root", 9 | imports: [RouterOutlet, AsyncPipe], 10 | templateUrl: "./app.component.html", 11 | styleUrl: "./app.component.css" 12 | }) 13 | export class AppComponent { 14 | title = "quinoa-app"; 15 | protected message: Observable = inject(HttpClient).get( 16 | "/bar/foo/api/quinoa", 17 | { 18 | responseType: "text", 19 | } 20 | ); 21 | } 22 | -------------------------------------------------------------------------------- /integration-tests/src/main/ui-angular-esbuild/src/app/app.config.ts: -------------------------------------------------------------------------------- 1 | import { ApplicationConfig, provideZoneChangeDetection } from '@angular/core'; 2 | import { provideRouter } from '@angular/router'; 3 | 4 | import { routes } from './app.routes'; 5 | import { provideHttpClient, withFetch } from '@angular/common/http'; 6 | 7 | export const appConfig: ApplicationConfig = { 8 | providers: [ 9 | provideZoneChangeDetection({ eventCoalescing: true }), 10 | provideRouter(routes), 11 | provideHttpClient(withFetch()), 12 | ], 13 | }; 14 | -------------------------------------------------------------------------------- /integration-tests/src/main/ui-angular-esbuild/src/app/app.routes.ts: -------------------------------------------------------------------------------- 1 | import { Routes } from '@angular/router'; 2 | 3 | export const routes: Routes = []; 4 | -------------------------------------------------------------------------------- /integration-tests/src/main/ui-angular-esbuild/src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | QuinoaApp 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /integration-tests/src/main/ui-angular-esbuild/src/main.ts: -------------------------------------------------------------------------------- 1 | import { bootstrapApplication } from '@angular/platform-browser'; 2 | import { appConfig } from './app/app.config'; 3 | import { AppComponent } from './app/app.component'; 4 | 5 | bootstrapApplication(AppComponent, appConfig) 6 | .catch((err) => console.error(err)); 7 | -------------------------------------------------------------------------------- /integration-tests/src/main/ui-angular-esbuild/src/styles.css: -------------------------------------------------------------------------------- 1 | /* You can add global styles to this file, and also import other style files */ 2 | -------------------------------------------------------------------------------- /integration-tests/src/main/ui-angular-esbuild/tsconfig.app.json: -------------------------------------------------------------------------------- 1 | /* To learn more about Typescript configuration file: https://www.typescriptlang.org/docs/handbook/tsconfig-json.html. */ 2 | /* To learn more about Angular compiler options: https://angular.dev/reference/configs/angular-compiler-options. */ 3 | { 4 | "extends": "./tsconfig.json", 5 | "compilerOptions": { 6 | "outDir": "./out-tsc/app", 7 | "types": [] 8 | }, 9 | "files": [ 10 | "src/main.ts" 11 | ], 12 | "include": [ 13 | "src/**/*.d.ts" 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /integration-tests/src/main/ui-angular-esbuild/tsconfig.json: -------------------------------------------------------------------------------- 1 | /* To learn more about Typescript configuration file: https://www.typescriptlang.org/docs/handbook/tsconfig-json.html. */ 2 | /* To learn more about Angular compiler options: https://angular.dev/reference/configs/angular-compiler-options. */ 3 | { 4 | "compileOnSave": false, 5 | "compilerOptions": { 6 | "outDir": "./dist/out-tsc", 7 | "strict": true, 8 | "noImplicitOverride": true, 9 | "noPropertyAccessFromIndexSignature": true, 10 | "noImplicitReturns": true, 11 | "noFallthroughCasesInSwitch": true, 12 | "skipLibCheck": true, 13 | "esModuleInterop": true, 14 | "sourceMap": true, 15 | "declaration": false, 16 | "experimentalDecorators": true, 17 | "moduleResolution": "bundler", 18 | "importHelpers": true, 19 | "target": "ES2022", 20 | "module": "ES2022", 21 | "useDefineForClassFields": false, 22 | "lib": [ 23 | "ES2022", 24 | "dom" 25 | ] 26 | }, 27 | "angularCompilerOptions": { 28 | "enableI18nLegacyMessageIdFormat": false, 29 | "strictInjectionParameters": true, 30 | "strictInputAccessModifiers": true, 31 | "strictTemplates": true 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /integration-tests/src/main/ui-angular-esbuild/tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | /* To learn more about Typescript configuration file: https://www.typescriptlang.org/docs/handbook/tsconfig-json.html. */ 2 | /* To learn more about Angular compiler options: https://angular.dev/reference/configs/angular-compiler-options. */ 3 | { 4 | "extends": "./tsconfig.json", 5 | "compilerOptions": { 6 | "outDir": "./out-tsc/spec", 7 | "types": [ 8 | "jasmine" 9 | ] 10 | }, 11 | "include": [ 12 | "src/**/*.spec.ts", 13 | "src/**/*.d.ts" 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /integration-tests/src/main/ui-angular/.gitignore: -------------------------------------------------------------------------------- 1 | /build/ 2 | /benchpress-build/ 3 | .DS_Store 4 | gen_docs.disable 5 | test.disable 6 | regression/temp*.html 7 | performance/temp*.html 8 | .idea/workspace.xml 9 | *~ 10 | *.swp 11 | .angular 12 | angular.js.tmproj 13 | node_modules/ 14 | angular.xcodeproj 15 | .firebase/ 16 | .idea 17 | 18 | .yarn/* 19 | !.yarn/patches 20 | !.yarn/plugins 21 | !.yarn/releases 22 | !.yarn/sdks 23 | !.yarn/versions 24 | 25 | *.iml 26 | .agignore 27 | .lvimrc 28 | libpeerconnection.log 29 | npm-debug.log 30 | /tmp/ 31 | .vscode 32 | *.log 33 | *.stackdump 34 | scripts/code.angularjs.org-firebase/deploy 35 | scripts/docs.angularjs.org-firebase/deploy 36 | scripts/docs.angularjs.org-firebase/functions/content 37 | Terms 38 | Privacy 39 | Security 40 | Status 41 | Docs 42 | Contact GitHub 43 | Pricing 44 | API 45 | Training 46 | Blog 47 | About 48 | -------------------------------------------------------------------------------- /integration-tests/src/main/ui-angular/.yarnrc.yml: -------------------------------------------------------------------------------- 1 | nodeLinker: node-modules 2 | 3 | yarnPath: .yarn/releases/yarn-3.6.3.cjs 4 | -------------------------------------------------------------------------------- /integration-tests/src/main/ui-angular/README.md: -------------------------------------------------------------------------------- 1 | # QuinoaApp 2 | 3 | This project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 13.3.0. 4 | 5 | ## Development server 6 | 7 | Run `ng serve` for a dev server. Navigate to `http://localhost:4200/`. The application will automatically reload if you change any of the source files. 8 | 9 | ## Code scaffolding 10 | 11 | Run `ng generate component component-name` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module`. 12 | 13 | ## Build 14 | 15 | Run `ng build` to build the project. The build artifacts will be stored in the `dist/` directory. 16 | 17 | ## Running unit tests 18 | 19 | Run `ng test` to execute the unit tests via [Karma](https://karma-runner.github.io). 20 | 21 | ## Running end-to-end tests 22 | 23 | Run `ng e2e` to execute the end-to-end tests via a platform of your choice. To use this command, you need to first add a package that implements end-to-end testing capabilities. 24 | 25 | ## Further help 26 | 27 | To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI Overview and Command Reference](https://angular.io/cli) page. 28 | -------------------------------------------------------------------------------- /integration-tests/src/main/ui-angular/karma.conf.js: -------------------------------------------------------------------------------- 1 | // Karma configuration file, see link for more information 2 | // https://karma-runner.github.io/1.0/config/configuration-file.html 3 | 4 | module.exports = function (config) { 5 | config.set({ 6 | basePath: '', 7 | frameworks: ['jasmine', '@angular-devkit/build-angular'], 8 | plugins: [ 9 | require('karma-jasmine'), 10 | require('karma-chrome-launcher'), 11 | require('karma-jasmine-html-reporter'), 12 | require('karma-coverage'), 13 | require('@angular-devkit/build-angular/plugins/karma') 14 | ], 15 | client: { 16 | jasmine: { 17 | // you can add configuration options for Jasmine here 18 | // the possible options are listed at https://jasmine.github.io/api/edge/Configuration.html 19 | // for example, you can disable the random execution with `random: false` 20 | // or set a specific seed with `seed: 4321` 21 | }, 22 | clearContext: false // leave Jasmine Spec Runner output visible in browser 23 | }, 24 | jasmineHtmlReporter: { 25 | suppressAll: true // removes the duplicated traces 26 | }, 27 | coverageReporter: { 28 | dir: require('path').join(__dirname, './coverage/quinoa-app'), 29 | subdir: '.', 30 | reporters: [ 31 | { type: 'html' }, 32 | { type: 'text-summary' } 33 | ] 34 | }, 35 | reporters: ['progress', 'kjhtml'], 36 | port: 9876, 37 | colors: true, 38 | logLevel: config.LOG_INFO, 39 | autoWatch: true, 40 | browsers: ['Chrome', 'ChromeHeadless', 'ChromeHeadlessCI'], 41 | customLaunchers: { 42 | ChromeHeadlessCI: { 43 | base: 'ChromeHeadless', 44 | flags: ['--no-sandbox'] 45 | } 46 | }, 47 | singleRun: false, 48 | restartOnFileChange: true 49 | }); 50 | }; 51 | -------------------------------------------------------------------------------- /integration-tests/src/main/ui-angular/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "quinoa-app", 3 | "version": "0.0.0", 4 | "scripts": { 5 | "ng": "ng", 6 | "start": "ng serve", 7 | "build": "npm run something && ng build", 8 | "something": "echo \"something\"", 9 | "watch": "ng build --watch --configuration development", 10 | "test": "ng test -- --no-watch --no-progress --browsers=ChromeHeadlessCI" 11 | }, 12 | "private": true, 13 | "dependencies": { 14 | "@angular/animations": "~13.3.0", 15 | "@angular/common": "~13.3.0", 16 | "@angular/compiler": "~13.3.0", 17 | "@angular/core": "~13.3.0", 18 | "@angular/forms": "~13.3.0", 19 | "@angular/platform-browser": "~13.3.0", 20 | "@angular/platform-browser-dynamic": "~13.3.0", 21 | "@angular/router": "~13.3.0", 22 | "rxjs": "~7.5.0", 23 | "tslib": "2.6.2", 24 | "zone.js": "~0.11.4" 25 | }, 26 | "devDependencies": { 27 | "@angular-devkit/build-angular": "~13.3.0", 28 | "@angular/cli": "~13.3.0", 29 | "@angular/compiler-cli": "~13.3.0", 30 | "@types/jasmine": "~3.10.0", 31 | "@types/node": "^12.11.1", 32 | "jasmine-core": "~4.0.0", 33 | "karma": "~6.3.0", 34 | "karma-chrome-launcher": "~3.1.0", 35 | "karma-coverage": "~2.1.0", 36 | "karma-jasmine": "~4.0.0", 37 | "karma-jasmine-html-reporter": "~1.7.0", 38 | "typescript": "~4.6.2" 39 | }, 40 | "packageManager": "yarn@3.6.3" 41 | } 42 | -------------------------------------------------------------------------------- /integration-tests/src/main/ui-angular/src/app/app-routing.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { RouterModule, Routes } from '@angular/router'; 3 | 4 | const routes: Routes = []; 5 | 6 | @NgModule({ 7 | imports: [RouterModule.forRoot(routes)], 8 | exports: [RouterModule] 9 | }) 10 | export class AppRoutingModule { } 11 | -------------------------------------------------------------------------------- /integration-tests/src/main/ui-angular/src/app/app.component.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quarkiverse/quarkus-quinoa/0ac98ea681988f670358498f91cb171bb870fd32/integration-tests/src/main/ui-angular/src/app/app.component.scss -------------------------------------------------------------------------------- /integration-tests/src/main/ui-angular/src/app/app.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { TestBed } from '@angular/core/testing'; 2 | import { RouterTestingModule } from '@angular/router/testing'; 3 | import { AppComponent } from './app.component'; 4 | 5 | describe('AppComponent', () => { 6 | beforeEach(async () => { 7 | await TestBed.configureTestingModule({ 8 | imports: [ 9 | RouterTestingModule 10 | ], 11 | declarations: [ 12 | AppComponent 13 | ], 14 | }).compileComponents(); 15 | }); 16 | 17 | it('should create the app', () => { 18 | const fixture = TestBed.createComponent(AppComponent); 19 | const app = fixture.componentInstance; 20 | expect(app).toBeTruthy(); 21 | }); 22 | 23 | it(`should have as title 'quinoa-app'`, () => { 24 | const fixture = TestBed.createComponent(AppComponent); 25 | const app = fixture.componentInstance; 26 | expect(app.title).toEqual('quinoa-app'); 27 | }); 28 | 29 | it('should render title', () => { 30 | const fixture = TestBed.createComponent(AppComponent); 31 | fixture.detectChanges(); 32 | const compiled = fixture.nativeElement as HTMLElement; 33 | expect(compiled.querySelector('.content span')?.textContent).toContain('quinoa-app app is running!'); 34 | }); 35 | }); 36 | -------------------------------------------------------------------------------- /integration-tests/src/main/ui-angular/src/app/app.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | import { HttpClient } from '@angular/common/http'; 3 | 4 | @Component({ 5 | selector: 'app-root', 6 | templateUrl: './app.component.html', 7 | styleUrls: ['./app.component.scss'] 8 | }) 9 | export class AppComponent { 10 | title = 'quinoa-app'; 11 | message?: string = undefined; 12 | 13 | constructor(private http:HttpClient) { } 14 | 15 | ngOnInit():void { 16 | this.http.get("/bar/foo/api/quinoa", {responseType: 'text'}).subscribe(data => { 17 | this.message = data as string 18 | }) 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /integration-tests/src/main/ui-angular/src/app/app.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { BrowserModule } from '@angular/platform-browser'; 3 | import { HttpClientModule } from '@angular/common/http'; 4 | 5 | import { AppRoutingModule } from './app-routing.module'; 6 | import { AppComponent } from './app.component'; 7 | 8 | @NgModule({ 9 | declarations: [ 10 | AppComponent 11 | ], 12 | imports: [ 13 | BrowserModule, 14 | AppRoutingModule, 15 | HttpClientModule 16 | ], 17 | providers: [], 18 | bootstrap: [AppComponent] 19 | }) 20 | export class AppModule { } 21 | -------------------------------------------------------------------------------- /integration-tests/src/main/ui-angular/src/assets/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quarkiverse/quarkus-quinoa/0ac98ea681988f670358498f91cb171bb870fd32/integration-tests/src/main/ui-angular/src/assets/.gitkeep -------------------------------------------------------------------------------- /integration-tests/src/main/ui-angular/src/environments/environment.prod.ts: -------------------------------------------------------------------------------- 1 | export const environment = { 2 | production: true 3 | }; 4 | -------------------------------------------------------------------------------- /integration-tests/src/main/ui-angular/src/environments/environment.ts: -------------------------------------------------------------------------------- 1 | // This file can be replaced during build by using the `fileReplacements` array. 2 | // `ng build` replaces `environment.ts` with `environment.prod.ts`. 3 | // The list of file replacements can be found in `angular.json`. 4 | 5 | export const environment = { 6 | production: false 7 | }; 8 | 9 | /* 10 | * For easier debugging in development mode, you can import the following file 11 | * to ignore zone related error stack frames such as `zone.run`, `zoneDelegate.invokeTask`. 12 | * 13 | * This import should be commented out in production mode because it will have a negative impact 14 | * on performance if an error is thrown. 15 | */ 16 | // import 'zone.js/plugins/zone-error'; // Included with Angular CLI. 17 | -------------------------------------------------------------------------------- /integration-tests/src/main/ui-angular/src/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quarkiverse/quarkus-quinoa/0ac98ea681988f670358498f91cb171bb870fd32/integration-tests/src/main/ui-angular/src/favicon.ico -------------------------------------------------------------------------------- /integration-tests/src/main/ui-angular/src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | QuinoaApp 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /integration-tests/src/main/ui-angular/src/main.ts: -------------------------------------------------------------------------------- 1 | import { enableProdMode } from '@angular/core'; 2 | import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; 3 | 4 | import { AppModule } from './app/app.module'; 5 | import { environment } from './environments/environment'; 6 | 7 | if (environment.production) { 8 | enableProdMode(); 9 | } 10 | 11 | platformBrowserDynamic().bootstrapModule(AppModule) 12 | .catch(err => console.error(err)); 13 | -------------------------------------------------------------------------------- /integration-tests/src/main/ui-angular/src/polyfills.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This file includes polyfills needed by Angular and is loaded before the app. 3 | * You can add your own extra polyfills to this file. 4 | * 5 | * This file is divided into 2 sections: 6 | * 1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers. 7 | * 2. Application imports. Files imported after ZoneJS that should be loaded before your main 8 | * file. 9 | * 10 | * The current setup is for so-called "evergreen" browsers; the last versions of browsers that 11 | * automatically update themselves. This includes recent versions of Safari, Chrome (including 12 | * Opera), Edge on the desktop, and iOS and Chrome on mobile. 13 | * 14 | * Learn more in https://angular.io/guide/browser-support 15 | */ 16 | 17 | /*************************************************************************************************** 18 | * BROWSER POLYFILLS 19 | */ 20 | 21 | /** 22 | * By default, zone.js will patch all possible macroTask and DomEvents 23 | * user can disable parts of macroTask/DomEvents patch by setting following flags 24 | * because those flags need to be set before `zone.js` being loaded, and webpack 25 | * will put import in the top of bundle, so user need to create a separate file 26 | * in this directory (for example: zone-flags.ts), and put the following flags 27 | * into that file, and then add the following code before importing zone.js. 28 | * import './zone-flags'; 29 | * 30 | * The flags allowed in zone-flags.ts are listed here. 31 | * 32 | * The following flags will work for all browsers. 33 | * 34 | * (window as any).__Zone_disable_requestAnimationFrame = true; // disable patch requestAnimationFrame 35 | * (window as any).__Zone_disable_on_property = true; // disable patch onProperty such as onclick 36 | * (window as any).__zone_symbol__UNPATCHED_EVENTS = ['scroll', 'mousemove']; // disable patch specified eventNames 37 | * 38 | * in IE/Edge developer tools, the addEventListener will also be wrapped by zone.js 39 | * with the following flag, it will bypass `zone.js` patch for IE/Edge 40 | * 41 | * (window as any).__Zone_enable_cross_context_check = true; 42 | * 43 | */ 44 | 45 | /*************************************************************************************************** 46 | * Zone JS is required by default for Angular itself. 47 | */ 48 | import 'zone.js'; // Included with Angular CLI. 49 | 50 | 51 | /*************************************************************************************************** 52 | * APPLICATION IMPORTS 53 | */ 54 | -------------------------------------------------------------------------------- /integration-tests/src/main/ui-angular/src/styles.scss: -------------------------------------------------------------------------------- 1 | /* You can add global styles to this file, and also import other style files */ 2 | -------------------------------------------------------------------------------- /integration-tests/src/main/ui-angular/src/test.ts: -------------------------------------------------------------------------------- 1 | // This file is required by karma.conf.js and loads recursively all the .spec and framework files 2 | 3 | import 'zone.js/testing'; 4 | import { getTestBed } from '@angular/core/testing'; 5 | import { 6 | BrowserDynamicTestingModule, 7 | platformBrowserDynamicTesting 8 | } from '@angular/platform-browser-dynamic/testing'; 9 | 10 | declare const require: { 11 | context(path: string, deep?: boolean, filter?: RegExp): { 12 | (id: string): T; 13 | keys(): string[]; 14 | }; 15 | }; 16 | 17 | // First, initialize the Angular testing environment. 18 | getTestBed().initTestEnvironment( 19 | BrowserDynamicTestingModule, 20 | platformBrowserDynamicTesting(), 21 | ); 22 | 23 | // Then we find all the tests. 24 | const context = require.context('./', true, /\.spec\.ts$/); 25 | // And load the modules. 26 | context.keys().map(context); 27 | -------------------------------------------------------------------------------- /integration-tests/src/main/ui-angular/tsconfig.app.json: -------------------------------------------------------------------------------- 1 | /* To learn more about this file see: https://angular.io/config/tsconfig. */ 2 | { 3 | "extends": "./tsconfig.json", 4 | "compilerOptions": { 5 | "outDir": "./out-tsc/app", 6 | "types": [] 7 | }, 8 | "files": [ 9 | "src/main.ts", 10 | "src/polyfills.ts" 11 | ], 12 | "include": [ 13 | "src/**/*.d.ts" 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /integration-tests/src/main/ui-angular/tsconfig.json: -------------------------------------------------------------------------------- 1 | /* To learn more about this file see: https://angular.io/config/tsconfig. */ 2 | { 3 | "compileOnSave": false, 4 | "compilerOptions": { 5 | "baseUrl": "./", 6 | "outDir": "./dist/out-tsc", 7 | "forceConsistentCasingInFileNames": true, 8 | "strict": true, 9 | "noImplicitOverride": true, 10 | "noPropertyAccessFromIndexSignature": true, 11 | "noImplicitReturns": true, 12 | "noFallthroughCasesInSwitch": true, 13 | "sourceMap": true, 14 | "declaration": false, 15 | "downlevelIteration": true, 16 | "experimentalDecorators": true, 17 | "moduleResolution": "node", 18 | "importHelpers": true, 19 | "target": "es2017", 20 | "module": "es2020", 21 | "lib": [ 22 | "es2020", 23 | "dom" 24 | ] 25 | }, 26 | "angularCompilerOptions": { 27 | "enableI18nLegacyMessageIdFormat": false, 28 | "strictInjectionParameters": true, 29 | "strictInputAccessModifiers": true, 30 | "strictTemplates": true 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /integration-tests/src/main/ui-angular/tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | /* To learn more about this file see: https://angular.io/config/tsconfig. */ 2 | { 3 | "extends": "./tsconfig.json", 4 | "compilerOptions": { 5 | "outDir": "./out-tsc/spec", 6 | "types": [ 7 | "jasmine" 8 | ] 9 | }, 10 | "files": [ 11 | "src/test.ts", 12 | "src/polyfills.ts" 13 | ], 14 | "include": [ 15 | "src/**/*.spec.ts", 16 | "src/**/*.d.ts" 17 | ] 18 | } 19 | -------------------------------------------------------------------------------- /integration-tests/src/main/ui-lit/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "quinoa-app", 3 | "version": "0.0.0", 4 | "private": true, 5 | "scripts": { 6 | "build-per-env:production": "webpack --mode=production", 7 | "build-per-env:development": "webpack --mode=development", 8 | "build-per-env": "by-node-env", 9 | "test": "" 10 | }, 11 | "dependencies": { 12 | "lit": "^2.8.0" 13 | }, 14 | "browser": { 15 | "[module-name]": false 16 | }, 17 | "devDependencies": { 18 | "by-node-env": "^2.0.1", 19 | "copy-webpack-plugin": "^11.0.0", 20 | "cross-env": "^7.0.3", 21 | "webpack": "^5.94.0", 22 | "webpack-cli": "^5.1.4" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /integration-tests/src/main/ui-lit/public/app.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Quinoa Lit App 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /integration-tests/src/main/ui-lit/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quarkiverse/quarkus-quinoa/0ac98ea681988f670358498f91cb171bb870fd32/integration-tests/src/main/ui-lit/public/favicon.ico -------------------------------------------------------------------------------- /integration-tests/src/main/ui-lit/src/simple-greeting.js: -------------------------------------------------------------------------------- 1 | import {html, css, LitElement} from 'lit'; 2 | 3 | const API_PATH = process.env.API_PATH; 4 | 5 | export class SimpleGreeting extends LitElement { 6 | static styles = css`p { color: blue }`; 7 | 8 | static properties = { 9 | name: {type: String}, 10 | }; 11 | 12 | constructor() { 13 | super(); 14 | this.name = 'Somebody'; 15 | } 16 | 17 | render() { 18 | const xmlHttp = new XMLHttpRequest(); 19 | 20 | xmlHttp.open( "GET", `${API_PATH}quinoa`, false ); 21 | xmlHttp.send( null ); 22 | const response = xmlHttp.responseText; 23 | return html`

${response} and ${this.name} and ${process.env.FOO}

`; 24 | } 25 | } 26 | customElements.define('simple-greeting', SimpleGreeting); 27 | -------------------------------------------------------------------------------- /integration-tests/src/main/ui-lit/webpack.config.js: -------------------------------------------------------------------------------- 1 | const { EnvironmentPlugin } = require('webpack'); 2 | const CopyWebpackPlugin = require('copy-webpack-plugin'); 3 | 4 | module.exports = { 5 | entry: "./src/simple-greeting.js", 6 | output: { 7 | filename: "simple-greeting.js" 8 | }, 9 | plugins: [ 10 | new CopyWebpackPlugin({ 11 | patterns: [ 12 | { from: 'public' } 13 | ] 14 | }), 15 | new EnvironmentPlugin(['FOO', 'ROOT_PATH', 'API_PATH']) 16 | ] 17 | }; -------------------------------------------------------------------------------- /integration-tests/src/main/ui-react/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | -------------------------------------------------------------------------------- /integration-tests/src/main/ui-react/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "quinoa", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@testing-library/jest-dom": "^5.16.5", 7 | "@testing-library/react": "^14.0.0", 8 | "@testing-library/user-event": "^14.4.3", 9 | "react": "^18.2.0", 10 | "react-dom": "^18.2.0", 11 | "react-scripts": "^5.0.1", 12 | "web-vitals": "^3.3.2" 13 | }, 14 | "scripts": { 15 | "start": "react-scripts start", 16 | "build": "react-scripts build", 17 | "test": "react-scripts test", 18 | "eject": "react-scripts eject" 19 | }, 20 | "eslintConfig": { 21 | "extends": [ 22 | "react-app", 23 | "react-app/jest" 24 | ] 25 | }, 26 | "browserslist": { 27 | "production": [ 28 | ">0.2%", 29 | "not dead", 30 | "not op_mini all" 31 | ], 32 | "development": [ 33 | "last 1 chrome version", 34 | "last 1 firefox version", 35 | "last 1 safari version" 36 | ] 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /integration-tests/src/main/ui-react/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quarkiverse/quarkus-quinoa/0ac98ea681988f670358498f91cb171bb870fd32/integration-tests/src/main/ui-react/public/favicon.ico -------------------------------------------------------------------------------- /integration-tests/src/main/ui-react/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 12 | 13 | 17 | 18 | 27 | React App 28 | 29 | 30 | 31 |
32 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /integration-tests/src/main/ui-react/public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quarkiverse/quarkus-quinoa/0ac98ea681988f670358498f91cb171bb870fd32/integration-tests/src/main/ui-react/public/logo192.png -------------------------------------------------------------------------------- /integration-tests/src/main/ui-react/public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quarkiverse/quarkus-quinoa/0ac98ea681988f670358498f91cb171bb870fd32/integration-tests/src/main/ui-react/public/logo512.png -------------------------------------------------------------------------------- /integration-tests/src/main/ui-react/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /integration-tests/src/main/ui-react/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /integration-tests/src/main/ui-react/src/App.css: -------------------------------------------------------------------------------- 1 | .App { 2 | text-align: center; 3 | } 4 | 5 | .App-logo { 6 | height: 40vmin; 7 | pointer-events: none; 8 | } 9 | 10 | @media (prefers-reduced-motion: no-preference) { 11 | .App-logo { 12 | animation: App-logo-spin infinite 20s linear; 13 | } 14 | } 15 | 16 | .App-header { 17 | background-color: #282c34; 18 | min-height: 100vh; 19 | display: flex; 20 | flex-direction: column; 21 | align-items: center; 22 | justify-content: center; 23 | font-size: calc(10px + 2vmin); 24 | color: white; 25 | } 26 | 27 | .App-link { 28 | color: #61dafb; 29 | } 30 | 31 | @keyframes App-logo-spin { 32 | from { 33 | transform: rotate(0deg); 34 | } 35 | to { 36 | transform: rotate(360deg); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /integration-tests/src/main/ui-react/src/App.js: -------------------------------------------------------------------------------- 1 | import { useEffect, useState } from "react"; 2 | import logo from './logo.svg'; 3 | import './App.css'; 4 | 5 | async function fetchQuinoa(setValue) { 6 | let response = await fetch('api/quinoa') 7 | response = await response.text() 8 | setValue(response) 9 | } 10 | 11 | function App() { 12 | const [value, setValue] = useState(null); 13 | useEffect(() => { 14 | if(value == null) { 15 | fetchQuinoa(setValue); 16 | } 17 | }, [value, setValue]); 18 | return ( 19 |
20 |
21 | logo 22 |

23 | {value || "loading from api..."} 24 |

25 | 31 | Learn React 32 | 33 |
34 |
35 | ); 36 | } 37 | 38 | export default App; 39 | -------------------------------------------------------------------------------- /integration-tests/src/main/ui-react/src/App.test.js: -------------------------------------------------------------------------------- 1 | import { render, screen } from '@testing-library/react'; 2 | import App from './App'; 3 | 4 | test('renders learn react link', () => { 5 | render(); 6 | const linkElement = screen.getByText(/learn react/i); 7 | expect(linkElement).toBeInTheDocument(); 8 | }); 9 | -------------------------------------------------------------------------------- /integration-tests/src/main/ui-react/src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 4 | 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', 5 | sans-serif; 6 | -webkit-font-smoothing: antialiased; 7 | -moz-osx-font-smoothing: grayscale; 8 | } 9 | 10 | code { 11 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', 12 | monospace; 13 | } 14 | -------------------------------------------------------------------------------- /integration-tests/src/main/ui-react/src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import './index.css'; 4 | import App from './App'; 5 | import reportWebVitals from './reportWebVitals'; 6 | 7 | ReactDOM.render( 8 | 9 | 10 | , 11 | document.getElementById('root') 12 | ); 13 | 14 | // If you want to start measuring performance in your app, pass a function 15 | // to log results (for example: reportWebVitals(console.log)) 16 | // or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals 17 | reportWebVitals(); 18 | -------------------------------------------------------------------------------- /integration-tests/src/main/ui-react/src/logo.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /integration-tests/src/main/ui-react/src/reportWebVitals.js: -------------------------------------------------------------------------------- 1 | const reportWebVitals = onPerfEntry => { 2 | if (onPerfEntry && onPerfEntry instanceof Function) { 3 | import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => { 4 | getCLS(onPerfEntry); 5 | getFID(onPerfEntry); 6 | getFCP(onPerfEntry); 7 | getLCP(onPerfEntry); 8 | getTTFB(onPerfEntry); 9 | }); 10 | } 11 | }; 12 | 13 | export default reportWebVitals; 14 | -------------------------------------------------------------------------------- /integration-tests/src/main/ui-react/src/setupTests.js: -------------------------------------------------------------------------------- 1 | // jest-dom adds custom jest matchers for asserting on DOM nodes. 2 | // allows you to do things like: 3 | // expect(element).toHaveTextContent(/react/i) 4 | // learn more: https://github.com/testing-library/jest-dom 5 | import '@testing-library/jest-dom'; 6 | -------------------------------------------------------------------------------- /integration-tests/src/main/ui-vue/.eslintrc.cjs: -------------------------------------------------------------------------------- 1 | /* eslint-env node */ 2 | require('@rushstack/eslint-patch/modern-module-resolution') 3 | 4 | module.exports = { 5 | root: true, 6 | 'extends': [ 7 | 'plugin:vue/vue3-essential', 8 | 'eslint:recommended', 9 | '@vue/eslint-config-prettier/skip-formatting' 10 | ], 11 | parserOptions: { 12 | ecmaVersion: 'latest' 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /integration-tests/src/main/ui-vue/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | .DS_Store 12 | dist 13 | dist-ssr 14 | coverage 15 | *.local 16 | 17 | /cypress/videos/ 18 | /cypress/screenshots/ 19 | 20 | # Editor directories and files 21 | .vscode/* 22 | !.vscode/extensions.json 23 | .idea 24 | *.suo 25 | *.ntvs* 26 | *.njsproj 27 | *.sln 28 | *.sw? 29 | -------------------------------------------------------------------------------- /integration-tests/src/main/ui-vue/.prettierrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json.schemastore.org/prettierrc", 3 | "semi": false, 4 | "tabWidth": 2, 5 | "singleQuote": true, 6 | "printWidth": 100, 7 | "trailingComma": "none" 8 | } -------------------------------------------------------------------------------- /integration-tests/src/main/ui-vue/README.md: -------------------------------------------------------------------------------- 1 | # vue-project 2 | 3 | This template should help get you started developing with Vue 3 in Vite. 4 | 5 | ## Recommended IDE Setup 6 | 7 | [VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin). 8 | 9 | ## Customize configuration 10 | 11 | See [Vite Configuration Reference](https://vitejs.dev/config/). 12 | 13 | ## Project Setup 14 | 15 | ```sh 16 | npm install 17 | ``` 18 | 19 | ### Compile and Hot-Reload for Development 20 | 21 | ```sh 22 | npm run dev 23 | ``` 24 | 25 | ### Compile and Minify for Production 26 | 27 | ```sh 28 | npm run build 29 | ``` 30 | 31 | ### Run Unit Tests with [Vitest](https://vitest.dev/) 32 | 33 | ```sh 34 | npm run test:unit 35 | ``` 36 | 37 | ### Lint with [ESLint](https://eslint.org/) 38 | 39 | ```sh 40 | npm run lint 41 | ``` 42 | -------------------------------------------------------------------------------- /integration-tests/src/main/ui-vue/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | hello-quinoa 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /integration-tests/src/main/ui-vue/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vue-project", 3 | "version": "0.0.0", 4 | "private": true, 5 | "scripts": { 6 | "dev": "vite", 7 | "build": "vite build", 8 | "preview": "vite preview", 9 | "test:unit": "vitest", 10 | "lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs --fix --ignore-path .gitignore", 11 | "format": "prettier --write src/" 12 | }, 13 | "dependencies": { 14 | "vue": "^3.5.13", 15 | "vue-router": "^4.5.0" 16 | }, 17 | "devDependencies": { 18 | "@rushstack/eslint-patch": "^1.11.0", 19 | "@vitejs/plugin-vue": "^5.2.3", 20 | "@vue/eslint-config-prettier": "^8.0.0", 21 | "@vue/test-utils": "^2.4.6", 22 | "eslint": "^8.57.1", 23 | "eslint-plugin-vue": "^9.33.0", 24 | "jsdom": "^22.1.0", 25 | "prettier": "^3.5.3", 26 | "vite": "^6.2.6", 27 | "vitest": "^3.1.1" 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /integration-tests/src/main/ui-vue/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quarkiverse/quarkus-quinoa/0ac98ea681988f670358498f91cb171bb870fd32/integration-tests/src/main/ui-vue/public/favicon.ico -------------------------------------------------------------------------------- /integration-tests/src/main/ui-vue/src/App.vue: -------------------------------------------------------------------------------- 1 | 5 | 6 | 22 | 23 | 86 | -------------------------------------------------------------------------------- /integration-tests/src/main/ui-vue/src/assets/base.css: -------------------------------------------------------------------------------- 1 | /* color palette from */ 2 | :root { 3 | --vt-c-white: #ffffff; 4 | --vt-c-white-soft: #f8f8f8; 5 | --vt-c-white-mute: #f2f2f2; 6 | 7 | --vt-c-black: #181818; 8 | --vt-c-black-soft: #222222; 9 | --vt-c-black-mute: #282828; 10 | 11 | --vt-c-indigo: #2c3e50; 12 | 13 | --vt-c-divider-light-1: rgba(60, 60, 60, 0.29); 14 | --vt-c-divider-light-2: rgba(60, 60, 60, 0.12); 15 | --vt-c-divider-dark-1: rgba(84, 84, 84, 0.65); 16 | --vt-c-divider-dark-2: rgba(84, 84, 84, 0.48); 17 | 18 | --vt-c-text-light-1: var(--vt-c-indigo); 19 | --vt-c-text-light-2: rgba(60, 60, 60, 0.66); 20 | --vt-c-text-dark-1: var(--vt-c-white); 21 | --vt-c-text-dark-2: rgba(235, 235, 235, 0.64); 22 | } 23 | 24 | /* semantic color variables for this project */ 25 | :root { 26 | --color-background: var(--vt-c-white); 27 | --color-background-soft: var(--vt-c-white-soft); 28 | --color-background-mute: var(--vt-c-white-mute); 29 | 30 | --color-border: var(--vt-c-divider-light-2); 31 | --color-border-hover: var(--vt-c-divider-light-1); 32 | 33 | --color-heading: var(--vt-c-text-light-1); 34 | --color-text: var(--vt-c-text-light-1); 35 | 36 | --section-gap: 160px; 37 | } 38 | 39 | @media (prefers-color-scheme: dark) { 40 | :root { 41 | --color-background: var(--vt-c-black); 42 | --color-background-soft: var(--vt-c-black-soft); 43 | --color-background-mute: var(--vt-c-black-mute); 44 | 45 | --color-border: var(--vt-c-divider-dark-2); 46 | --color-border-hover: var(--vt-c-divider-dark-1); 47 | 48 | --color-heading: var(--vt-c-text-dark-1); 49 | --color-text: var(--vt-c-text-dark-2); 50 | } 51 | } 52 | 53 | *, 54 | *::before, 55 | *::after { 56 | box-sizing: border-box; 57 | margin: 0; 58 | font-weight: normal; 59 | } 60 | 61 | body { 62 | min-height: 100vh; 63 | color: var(--color-text); 64 | background: var(--color-background); 65 | transition: 66 | color 0.5s, 67 | background-color 0.5s; 68 | line-height: 1.6; 69 | font-family: 70 | Inter, 71 | -apple-system, 72 | BlinkMacSystemFont, 73 | 'Segoe UI', 74 | Roboto, 75 | Oxygen, 76 | Ubuntu, 77 | Cantarell, 78 | 'Fira Sans', 79 | 'Droid Sans', 80 | 'Helvetica Neue', 81 | sans-serif; 82 | font-size: 15px; 83 | text-rendering: optimizeLegibility; 84 | -webkit-font-smoothing: antialiased; 85 | -moz-osx-font-smoothing: grayscale; 86 | } 87 | -------------------------------------------------------------------------------- /integration-tests/src/main/ui-vue/src/assets/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /integration-tests/src/main/ui-vue/src/assets/main.css: -------------------------------------------------------------------------------- 1 | @import './base.css'; 2 | 3 | #app { 4 | max-width: 1280px; 5 | margin: 0 auto; 6 | padding: 2rem; 7 | 8 | font-weight: normal; 9 | } 10 | 11 | a, 12 | .green { 13 | text-decoration: none; 14 | color: hsla(160, 100%, 37%, 1); 15 | transition: 0.4s; 16 | } 17 | 18 | @media (hover: hover) { 19 | a:hover { 20 | background-color: hsla(160, 100%, 37%, 0.2); 21 | } 22 | } 23 | 24 | @media (min-width: 1024px) { 25 | body { 26 | display: flex; 27 | place-items: center; 28 | } 29 | 30 | #app { 31 | display: grid; 32 | grid-template-columns: 1fr 1fr; 33 | padding: 0 2rem; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /integration-tests/src/main/ui-vue/src/components/HelloWorld.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 22 | 23 | 47 | -------------------------------------------------------------------------------- /integration-tests/src/main/ui-vue/src/components/WelcomeItem.vue: -------------------------------------------------------------------------------- 1 | 14 | 15 | 87 | -------------------------------------------------------------------------------- /integration-tests/src/main/ui-vue/src/components/__tests__/HelloWorld.spec.js: -------------------------------------------------------------------------------- 1 | import { describe, it, expect } from 'vitest' 2 | 3 | import { mount } from '@vue/test-utils' 4 | import HelloWorld from '../HelloWorld.vue' 5 | 6 | describe('HelloWorld', () => { 7 | it('renders properly', () => { 8 | const wrapper = mount(HelloWorld, { props: { msg: 'Hello Vitest' } }) 9 | expect(wrapper.text()).toContain('Hello Vitest') 10 | }) 11 | }) 12 | -------------------------------------------------------------------------------- /integration-tests/src/main/ui-vue/src/components/icons/IconCommunity.vue: -------------------------------------------------------------------------------- 1 | 8 | -------------------------------------------------------------------------------- /integration-tests/src/main/ui-vue/src/components/icons/IconDocumentation.vue: -------------------------------------------------------------------------------- 1 | 8 | -------------------------------------------------------------------------------- /integration-tests/src/main/ui-vue/src/components/icons/IconEcosystem.vue: -------------------------------------------------------------------------------- 1 | 8 | -------------------------------------------------------------------------------- /integration-tests/src/main/ui-vue/src/components/icons/IconSupport.vue: -------------------------------------------------------------------------------- 1 | 8 | -------------------------------------------------------------------------------- /integration-tests/src/main/ui-vue/src/components/icons/IconTooling.vue: -------------------------------------------------------------------------------- 1 | 2 | 20 | -------------------------------------------------------------------------------- /integration-tests/src/main/ui-vue/src/main.js: -------------------------------------------------------------------------------- 1 | import './assets/main.css' 2 | 3 | import { createApp } from 'vue' 4 | import App from './App.vue' 5 | import router from './router' 6 | 7 | const app = createApp(App) 8 | 9 | app.use(router) 10 | 11 | app.mount('#app') 12 | -------------------------------------------------------------------------------- /integration-tests/src/main/ui-vue/src/router/index.js: -------------------------------------------------------------------------------- 1 | import { createRouter, createWebHistory } from 'vue-router' 2 | import HomeView from '../views/HomeView.vue' 3 | 4 | const router = createRouter({ 5 | history: createWebHistory(import.meta.env.BASE_URL), 6 | routes: [ 7 | { 8 | path: '/', 9 | name: 'home', 10 | component: HomeView 11 | }, 12 | { 13 | path: '/about', 14 | name: 'about', 15 | // route level code-splitting 16 | // this generates a separate chunk (About.[hash].js) for this route 17 | // which is lazy-loaded when the route is visited. 18 | component: () => import('../views/AboutView.vue') 19 | } 20 | ] 21 | }) 22 | 23 | export default router 24 | -------------------------------------------------------------------------------- /integration-tests/src/main/ui-vue/src/views/AboutView.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 16 | -------------------------------------------------------------------------------- /integration-tests/src/main/ui-vue/src/views/HomeView.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 10 | -------------------------------------------------------------------------------- /integration-tests/src/main/ui-vue/vite.config.js: -------------------------------------------------------------------------------- 1 | import { fileURLToPath, URL } from 'node:url' 2 | 3 | import { defineConfig } from 'vite' 4 | import vue from '@vitejs/plugin-vue' 5 | 6 | // https://vitejs.dev/config/ 7 | export default defineConfig({ 8 | plugins: [ 9 | vue(), 10 | ], 11 | resolve: { 12 | alias: { 13 | '@': fileURLToPath(new URL('./src', import.meta.url)) 14 | } 15 | } 16 | }) 17 | -------------------------------------------------------------------------------- /integration-tests/src/main/ui-vue/vitest.config.js: -------------------------------------------------------------------------------- 1 | import { fileURLToPath } from 'node:url' 2 | import { mergeConfig, defineConfig, configDefaults } from 'vitest/config' 3 | import viteConfig from './vite.config' 4 | 5 | export default mergeConfig( 6 | viteConfig, 7 | defineConfig({ 8 | test: { 9 | environment: 'jsdom', 10 | exclude: [...configDefaults.exclude, 'e2e/*'], 11 | root: fileURLToPath(new URL('./', import.meta.url)) 12 | } 13 | }) 14 | ) 15 | -------------------------------------------------------------------------------- /integration-tests/src/test/java/io/quarkiverse/quinoa/it/QuinoaCodestartTest.java: -------------------------------------------------------------------------------- 1 | package io.quarkiverse.quinoa.it; 2 | 3 | import static io.quarkus.devtools.codestarts.quarkus.QuarkusCodestartCatalog.Language.JAVA; 4 | import static io.quarkus.devtools.testing.SnapshotTesting.checkContains; 5 | 6 | import org.junit.jupiter.api.Test; 7 | import org.junit.jupiter.api.extension.RegisterExtension; 8 | 9 | import io.quarkus.devtools.testing.codestarts.QuarkusCodestartTest; 10 | 11 | public class QuinoaCodestartTest { 12 | 13 | @RegisterExtension 14 | public static QuarkusCodestartTest codestartTest = QuarkusCodestartTest.builder() 15 | .setupStandaloneExtensionTest("io.quarkiverse.quinoa:quarkus-quinoa") 16 | .languages(JAVA) 17 | .build(); 18 | 19 | @Test 20 | void testContent() throws Throwable { 21 | codestartTest.assertThatGeneratedFile(JAVA, "src/main/webui/package.json") 22 | .exists(); 23 | codestartTest.assertThatGeneratedTreeMatchSnapshots(JAVA, "src/main/webui"); 24 | codestartTest.assertThatGeneratedFile(JAVA, ".gitignore") 25 | .satisfies(checkContains("node_modules/")); 26 | } 27 | 28 | @Test 29 | void testBuild() throws Throwable { 30 | codestartTest.buildAllProjects(); 31 | } 32 | 33 | } -------------------------------------------------------------------------------- /integration-tests/src/test/java/io/quarkiverse/quinoa/it/QuinoaRootPathTest.java: -------------------------------------------------------------------------------- 1 | package io.quarkiverse.quinoa.it; 2 | 3 | import java.net.URL; 4 | 5 | import org.junit.jupiter.api.Assertions; 6 | import org.junit.jupiter.api.Test; 7 | 8 | import com.microsoft.playwright.BrowserContext; 9 | import com.microsoft.playwright.ElementHandle; 10 | import com.microsoft.playwright.Page; 11 | import com.microsoft.playwright.Response; 12 | 13 | import io.quarkiverse.playwright.InjectPlaywright; 14 | import io.quarkiverse.playwright.WithPlaywright; 15 | import io.quarkus.test.common.http.TestHTTPResource; 16 | import io.quarkus.test.junit.QuarkusTest; 17 | import io.quarkus.test.junit.TestProfile; 18 | 19 | @QuarkusTest 20 | @TestProfile(TestProfiles.RootPathTests.class) 21 | @WithPlaywright 22 | public class QuinoaRootPathTest { 23 | 24 | @InjectPlaywright 25 | BrowserContext context; 26 | 27 | @TestHTTPResource("/") 28 | URL url; 29 | 30 | @TestHTTPResource("/some-route") 31 | URL urlRoute; 32 | 33 | @Test 34 | public void testUIIndex() { 35 | final Page page = context.newPage(); 36 | Response response = page.navigate(url.toString()); 37 | Assertions.assertEquals("OK", response.statusText()); 38 | 39 | page.waitForLoadState(); 40 | 41 | String title = page.title(); 42 | Assertions.assertEquals("Quinoa Lit App", title); 43 | 44 | // Make sure the component loaded and hits the backend 45 | final ElementHandle quinoaEl = page.waitForSelector(".greeting"); 46 | String greeting = quinoaEl.innerText(); 47 | Assertions.assertEquals("Hello Quinoa and World and bar", greeting); 48 | } 49 | 50 | @Test 51 | public void testRoute() { 52 | final Page page = context.newPage(); 53 | Response response = page.navigate(urlRoute.toString()); 54 | Assertions.assertEquals("OK", response.statusText()); 55 | 56 | page.waitForLoadState(); 57 | 58 | String title = page.title(); 59 | Assertions.assertEquals("Quinoa Lit App", title); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /integration-tests/src/test/java/io/quarkiverse/quinoa/it/QuinoaUIIT.java: -------------------------------------------------------------------------------- 1 | package io.quarkiverse.quinoa.it; 2 | 3 | import io.quarkus.test.junit.QuarkusIntegrationTest; 4 | 5 | @QuarkusIntegrationTest 6 | public class QuinoaUIIT extends QuinoaUIReactTest { 7 | } 8 | -------------------------------------------------------------------------------- /integration-tests/src/test/java/io/quarkiverse/quinoa/it/QuinoaUILitTest.java: -------------------------------------------------------------------------------- 1 | package io.quarkiverse.quinoa.it; 2 | 3 | import java.net.URL; 4 | 5 | import org.junit.jupiter.api.Assertions; 6 | import org.junit.jupiter.api.Test; 7 | 8 | import com.microsoft.playwright.BrowserContext; 9 | import com.microsoft.playwright.ElementHandle; 10 | import com.microsoft.playwright.Page; 11 | import com.microsoft.playwright.Response; 12 | 13 | import io.quarkiverse.playwright.InjectPlaywright; 14 | import io.quarkiverse.playwright.WithPlaywright; 15 | import io.quarkus.test.common.http.TestHTTPResource; 16 | import io.quarkus.test.junit.QuarkusTest; 17 | import io.quarkus.test.junit.TestProfile; 18 | 19 | @QuarkusTest 20 | @TestProfile(TestProfiles.LitTests.class) 21 | @WithPlaywright 22 | public class QuinoaUILitTest { 23 | 24 | @InjectPlaywright 25 | BrowserContext context; 26 | 27 | @TestHTTPResource("/") 28 | URL url; 29 | 30 | @Test 31 | public void testUIIndex() { 32 | final Page page = context.newPage(); 33 | Response response = page.navigate(url.toString()); 34 | Assertions.assertEquals("OK", response.statusText()); 35 | 36 | page.waitForLoadState(); 37 | 38 | String title = page.title(); 39 | Assertions.assertEquals("Quinoa Lit App", title); 40 | 41 | // Make sure the component loaded and hits the backend 42 | final ElementHandle quinoaEl = page.waitForSelector(".greeting"); 43 | String greeting = quinoaEl.innerText(); 44 | Assertions.assertEquals("Hello Quinoa and World and bar", greeting); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /integration-tests/src/test/java/io/quarkiverse/quinoa/it/QuinoaUIReactJustBuildTest.java: -------------------------------------------------------------------------------- 1 | package io.quarkiverse.quinoa.it; 2 | 3 | import static io.restassured.RestAssured.given; 4 | import static org.hamcrest.Matchers.is; 5 | 6 | import java.net.URL; 7 | 8 | import org.hamcrest.Matchers; 9 | import org.junit.jupiter.api.Test; 10 | 11 | import io.quarkus.test.common.http.TestHTTPResource; 12 | import io.quarkus.test.junit.QuarkusTest; 13 | import io.quarkus.test.junit.TestProfile; 14 | import io.restassured.http.ContentType; 15 | 16 | @QuarkusTest 17 | @TestProfile(TestProfiles.ReactJustBuildTests.class) 18 | public class QuinoaUIReactJustBuildTest { 19 | 20 | @TestHTTPResource("/") 21 | URL root; 22 | 23 | @TestHTTPResource("/logo192.png") 24 | URL logo; 25 | 26 | @TestHTTPResource("/api/quinoa") 27 | URL api; 28 | 29 | @Test 30 | public void testIndexFromResources() { 31 | given() 32 | .when().get(root) 33 | .then() 34 | .statusCode(200) 35 | .body(Matchers.equalTo("NOT QUINOA")); 36 | } 37 | 38 | @Test 39 | public void testLogo404() { 40 | given() 41 | .when().get(logo) 42 | .then() 43 | .statusCode(404); 44 | } 45 | 46 | @Test 47 | public void testHelloEndpoint() { 48 | given() 49 | .when().get(api) 50 | .then() 51 | .statusCode(200) 52 | .body(is("Hello Quinoa")); 53 | } 54 | 55 | @Test 56 | public void testHelloEndpointPost() { 57 | given() 58 | .body("bowl") 59 | .contentType(ContentType.TEXT) 60 | .when().post(api) 61 | .then() 62 | .statusCode(200) 63 | .body(is("Hello Quinoa bowl")); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /integration-tests/src/test/java/io/quarkiverse/quinoa/it/QuinoaUIReactTest.java: -------------------------------------------------------------------------------- 1 | package io.quarkiverse.quinoa.it; 2 | 3 | import static io.restassured.RestAssured.given; 4 | import static org.hamcrest.Matchers.is; 5 | 6 | import java.net.URL; 7 | 8 | import org.junit.jupiter.api.Assertions; 9 | import org.junit.jupiter.api.Test; 10 | 11 | import com.microsoft.playwright.BrowserContext; 12 | import com.microsoft.playwright.ElementHandle; 13 | import com.microsoft.playwright.Page; 14 | import com.microsoft.playwright.Response; 15 | 16 | import io.quarkiverse.playwright.InjectPlaywright; 17 | import io.quarkiverse.playwright.WithPlaywright; 18 | import io.quarkus.test.common.http.TestHTTPResource; 19 | import io.quarkus.test.junit.QuarkusTest; 20 | import io.quarkus.test.junit.TestProfile; 21 | import io.restassured.http.ContentType; 22 | 23 | @QuarkusTest 24 | @TestProfile(TestProfiles.ReactTests.class) 25 | @WithPlaywright 26 | public class QuinoaUIReactTest { 27 | 28 | @InjectPlaywright 29 | BrowserContext context; 30 | 31 | @TestHTTPResource("/index.html") 32 | URL url; 33 | 34 | @TestHTTPResource("/something") 35 | URL url404; 36 | 37 | @TestHTTPResource("/api/quinoa") 38 | URL api; 39 | 40 | @Test 41 | public void testUIIndex() { 42 | final Page page = context.newPage(); 43 | Response response = page.navigate(url.toString()); 44 | Assertions.assertEquals("OK", response.statusText()); 45 | 46 | page.waitForLoadState(); 47 | 48 | String title = page.title(); 49 | Assertions.assertEquals("React App", title); 50 | 51 | // Make sure the component loaded and hits the backend 52 | final ElementHandle quinoaEl = page.waitForSelector(".quinoa.loaded"); 53 | String greeting = quinoaEl.innerText(); 54 | Assertions.assertEquals("Hello Quinoa", greeting); 55 | } 56 | 57 | @Test 58 | public void test404Endpoint() { 59 | given() 60 | .when().get(url404) 61 | .then() 62 | .statusCode(404); 63 | } 64 | 65 | @Test 66 | public void testHelloEndpoint() { 67 | given() 68 | .when().get(api) 69 | .then() 70 | .statusCode(200) 71 | .body(is("Hello Quinoa")); 72 | } 73 | 74 | @Test 75 | public void testHelloEndpointPost() { 76 | given() 77 | .body("bowl") 78 | .contentType(ContentType.TEXT) 79 | .when().post(api) 80 | .then() 81 | .statusCode(200) 82 | .body(is("Hello Quinoa bowl")); 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /integration-tests/src/test/java/io/quarkiverse/quinoa/it/QuinoaUIVueTest.java: -------------------------------------------------------------------------------- 1 | package io.quarkiverse.quinoa.it; 2 | 3 | import java.net.URL; 4 | 5 | import org.junit.jupiter.api.Assertions; 6 | import org.junit.jupiter.api.Test; 7 | 8 | import com.microsoft.playwright.BrowserContext; 9 | import com.microsoft.playwright.Page; 10 | import com.microsoft.playwright.Response; 11 | 12 | import io.quarkiverse.playwright.InjectPlaywright; 13 | import io.quarkiverse.playwright.WithPlaywright; 14 | import io.quarkus.test.common.http.TestHTTPResource; 15 | import io.quarkus.test.junit.QuarkusTest; 16 | import io.quarkus.test.junit.TestProfile; 17 | 18 | @QuarkusTest 19 | @TestProfile(TestProfiles.VueTests.class) 20 | @WithPlaywright 21 | public class QuinoaUIVueTest { 22 | 23 | @InjectPlaywright 24 | BrowserContext context; 25 | 26 | @TestHTTPResource("/") 27 | URL url; 28 | 29 | @Test 30 | public void testUIIndex() { 31 | final Page page = context.newPage(); 32 | Response response = page.navigate(url.toString()); 33 | Assertions.assertEquals("OK", response.statusText()); 34 | 35 | page.waitForLoadState(); 36 | 37 | String title = page.title(); 38 | Assertions.assertEquals("hello-quinoa", title); 39 | 40 | // Make sure the component loaded and hits the backend 41 | String greeting = page.textContent(".greetings h3").trim(); 42 | Assertions.assertEquals("You’ve successfully created a project with Quarkus + Quinoa + Vite + Vue 3.", greeting); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /integration-tests/src/test/java/io/quarkiverse/quinoa/it/QuinoaUIYarnTest.java: -------------------------------------------------------------------------------- 1 | package io.quarkiverse.quinoa.it; 2 | 3 | import static io.restassured.RestAssured.given; 4 | import static org.hamcrest.Matchers.containsString; 5 | 6 | import org.junit.jupiter.api.Test; 7 | 8 | import io.quarkus.test.junit.QuarkusTest; 9 | import io.quarkus.test.junit.TestProfile; 10 | 11 | @QuarkusTest 12 | @TestProfile(TestProfiles.YarnTests.class) 13 | public class QuinoaUIYarnTest { 14 | 15 | @Test 16 | public void testUIIndex() { 17 | given() 18 | .when().get("/") 19 | .then() 20 | .statusCode(200) 21 | .body(containsString("React App")); 22 | given() 23 | .when().get("/index.html") 24 | .then() 25 | .statusCode(200) 26 | .body(containsString("React App")); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /integration-tests/src/test/java/io/quarkiverse/quinoa/it/TestProfiles.java: -------------------------------------------------------------------------------- 1 | package io.quarkiverse.quinoa.it; 2 | 3 | import io.quarkiverse.quinoa.testing.QuinoaTestProfiles; 4 | 5 | public class TestProfiles { 6 | 7 | public static class YarnTests extends QuinoaTestProfiles.EnableAndRunTests { 8 | @Override 9 | public String getConfigProfile() { 10 | return "react,yarn"; 11 | } 12 | } 13 | 14 | public static class ReactTests extends QuinoaTestProfiles.Enable { 15 | @Override 16 | public String getConfigProfile() { 17 | return "react"; 18 | } 19 | } 20 | 21 | public static class ReactJustBuildTests extends QuinoaTestProfiles.Enable { 22 | @Override 23 | public String getConfigProfile() { 24 | return "react,just-build"; 25 | } 26 | } 27 | 28 | public static class AngularTests extends QuinoaTestProfiles.Enable { 29 | @Override 30 | public String getConfigProfile() { 31 | return "angular"; 32 | } 33 | } 34 | 35 | public static class AngularEsBuildTests extends QuinoaTestProfiles.Enable { 36 | @Override 37 | public String getConfigProfile() { 38 | return "angular-esbuild"; 39 | } 40 | } 41 | 42 | public static class LitTests extends QuinoaTestProfiles.Enable { 43 | @Override 44 | public String getConfigProfile() { 45 | return "lit"; 46 | } 47 | } 48 | 49 | public static class RootPathTests extends QuinoaTestProfiles.Enable { 50 | @Override 51 | public String getConfigProfile() { 52 | return "lit-root-path"; 53 | } 54 | } 55 | 56 | public static class UiRootPathTests extends QuinoaTestProfiles.Enable { 57 | @Override 58 | public String getConfigProfile() { 59 | return "lit-ui-root-path"; 60 | } 61 | } 62 | 63 | public static class VueTests extends QuinoaTestProfiles.Enable { 64 | @Override 65 | public String getConfigProfile() { 66 | return "vue"; 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /integration-tests/src/test/resources/__snapshots__/QuinoaCodestartTest/testContent/dir-tree.snapshot: -------------------------------------------------------------------------------- 1 | / 2 | counter.js 3 | index.html 4 | main.js 5 | package-lock.json 6 | package.json 7 | public/ 8 | public/quarkus.svg 9 | public/vite.svg 10 | style.css -------------------------------------------------------------------------------- /runtime/src/main/codestarts/quarkus/quinoa-codestart/base/..gitignore: -------------------------------------------------------------------------------- 1 | # Quinoa 2 | node_modules/ 3 | build/ 4 | dist/ 5 | .quinoa/ 6 | dist-ssr 7 | *.local 8 | 9 | # Logs 10 | logs/ 11 | *.log 12 | npm-debug.log* 13 | yarn-debug.log* 14 | yarn-error.log* 15 | pnpm-debug.log* 16 | lerna-debug.log* -------------------------------------------------------------------------------- /runtime/src/main/codestarts/quarkus/quinoa-codestart/base/README.tpl.qute.md: -------------------------------------------------------------------------------- 1 | {#include readme-header /} 2 | -------------------------------------------------------------------------------- /runtime/src/main/codestarts/quarkus/quinoa-codestart/base/src/main/java/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quarkiverse/quarkus-quinoa/0ac98ea681988f670358498f91cb171bb870fd32/runtime/src/main/codestarts/quarkus/quinoa-codestart/base/src/main/java/.gitkeep -------------------------------------------------------------------------------- /runtime/src/main/codestarts/quarkus/quinoa-codestart/base/src/main/resources/META-INF/resources/index.entry.qute.html: -------------------------------------------------------------------------------- 1 | {#include index-entry /} -------------------------------------------------------------------------------- /runtime/src/main/codestarts/quarkus/quinoa-codestart/base/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | quarkus: 2 | quinoa: 3 | package-manager-install: 4 | ~: true 5 | node-version: 20.10.0 6 | ui-root-path: quinoa 7 | -------------------------------------------------------------------------------- /runtime/src/main/codestarts/quarkus/quinoa-codestart/base/src/main/webui/counter.js: -------------------------------------------------------------------------------- 1 | export function setupCounter(element) { 2 | let counter = 0 3 | const setCounter = (count) => { 4 | counter = count 5 | element.innerHTML = `count is ${counter}` 6 | } 7 | element.addEventListener('click', () => setCounter(counter + 1)) 8 | setCounter(0) 9 | } 10 | -------------------------------------------------------------------------------- /runtime/src/main/codestarts/quarkus/quinoa-codestart/base/src/main/webui/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Quinoa App 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /runtime/src/main/codestarts/quarkus/quinoa-codestart/base/src/main/webui/main.js: -------------------------------------------------------------------------------- 1 | import './style.css' 2 | import quarkusLogo from '/quarkus.svg' 3 | import viteLogo from '/vite.svg' 4 | import { setupCounter } from './counter.js' 5 | 6 | document.querySelector('#app').innerHTML = ` 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |

Hello Quinoa!

15 |
16 | 17 |
18 |

19 | Quinoa is a Quarkus extension which eases the development, the build and serving of single page apps or web components (built with npm : React, Angular, Vue, Lit, Svelte, Astro, SolidJS …) alongside Quarkus. It is possible to use it with a Quarkus backend in a single project. 20 |

21 |
22 | ` 23 | 24 | setupCounter(document.querySelector('#counter')) 25 | -------------------------------------------------------------------------------- /runtime/src/main/codestarts/quarkus/quinoa-codestart/base/src/main/webui/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "quinoa-starter", 3 | "private": true, 4 | "version": "0.0.0", 5 | "type": "module", 6 | "scripts": { 7 | "dev": "vite --base=/quinoa", 8 | "build": "vite build --base=/quinoa", 9 | "preview": "vite preview --base=/quinoa" 10 | }, 11 | "devDependencies": { 12 | "vite": "^6.2.7" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /runtime/src/main/codestarts/quarkus/quinoa-codestart/base/src/main/webui/public/quarkus.svg: -------------------------------------------------------------------------------- 1 | quarkus_icon_rgb_1024px_reverse -------------------------------------------------------------------------------- /runtime/src/main/codestarts/quarkus/quinoa-codestart/base/src/main/webui/public/vite.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /runtime/src/main/codestarts/quarkus/quinoa-codestart/base/src/main/webui/style.css: -------------------------------------------------------------------------------- 1 | :root { 2 | font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif; 3 | line-height: 1.5; 4 | font-weight: 400; 5 | 6 | color-scheme: light dark; 7 | color: rgba(255, 255, 255, 0.87); 8 | background-color: #242424; 9 | 10 | font-synthesis: none; 11 | text-rendering: optimizeLegibility; 12 | -webkit-font-smoothing: antialiased; 13 | -moz-osx-font-smoothing: grayscale; 14 | } 15 | 16 | a { 17 | font-weight: 500; 18 | color: #646cff; 19 | text-decoration: inherit; 20 | } 21 | a:hover { 22 | color: #535bf2; 23 | } 24 | 25 | body { 26 | margin: 0; 27 | display: flex; 28 | place-items: center; 29 | min-width: 320px; 30 | min-height: 100vh; 31 | } 32 | 33 | h1 { 34 | font-size: 3.2em; 35 | line-height: 1.1; 36 | } 37 | 38 | #app { 39 | max-width: 1280px; 40 | margin: 0 auto; 41 | padding: 2rem; 42 | text-align: center; 43 | } 44 | 45 | .logo { 46 | height: 6em; 47 | padding: 1.5em; 48 | will-change: filter; 49 | transition: filter 300ms; 50 | } 51 | .logo:hover { 52 | filter: drop-shadow(0 0 2em #646cffaa); 53 | } 54 | .logo.vanilla:hover { 55 | filter: drop-shadow(0 0 2em #f7df1eaa); 56 | } 57 | 58 | .card { 59 | padding: 2em; 60 | } 61 | 62 | .read-the-docs { 63 | color: #888; 64 | } 65 | 66 | button { 67 | border-radius: 8px; 68 | border: 1px solid transparent; 69 | padding: 0.6em 1.2em; 70 | font-size: 1em; 71 | font-weight: 500; 72 | font-family: inherit; 73 | background-color: #1a1a1a; 74 | cursor: pointer; 75 | transition: border-color 0.25s; 76 | } 77 | button:hover { 78 | border-color: #646cff; 79 | } 80 | button:focus, 81 | button:focus-visible { 82 | outline: 4px auto -webkit-focus-ring-color; 83 | } 84 | 85 | @media (prefers-color-scheme: light) { 86 | :root { 87 | color: #213547; 88 | background-color: #ffffff; 89 | } 90 | a:hover { 91 | color: #747bff; 92 | } 93 | button { 94 | background-color: #f9f9f9; 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /runtime/src/main/codestarts/quarkus/quinoa-codestart/codestart.yml: -------------------------------------------------------------------------------- 1 | name: quinoa-codestart 2 | ref: quinoa 3 | type: code 4 | tags: extension-codestart 5 | metadata: 6 | title: Quinoa 7 | description: Quinoa codestart added a tiny Vite app in src/main/webui. The page is configured to be visible on /quinoa. 8 | path: /quinoa 9 | related-guide-section: https://quarkiverse.github.io/quarkiverse-docs/quarkus-quinoa/dev/index.html 10 | -------------------------------------------------------------------------------- /runtime/src/main/java/io/quarkiverse/quinoa/QuinoaDevProxyHandlerConfig.java: -------------------------------------------------------------------------------- 1 | package io.quarkiverse.quinoa; 2 | 3 | import java.util.List; 4 | import java.util.Objects; 5 | import java.util.Set; 6 | 7 | import io.quarkus.runtime.annotations.RecordableConstructor; 8 | 9 | public class QuinoaDevProxyHandlerConfig { 10 | public final List ignoredPathPrefixes; 11 | public final String indexPage; 12 | public final boolean enableCompression; 13 | public final Set compressMediaTypes; 14 | 15 | public final boolean devServerDirectForwarding; 16 | 17 | @RecordableConstructor 18 | public QuinoaDevProxyHandlerConfig(List ignoredPathPrefixes, String indexPage, boolean enableCompression, 19 | Set compressMediaTypes, boolean devServerDirectForwarding) { 20 | this.ignoredPathPrefixes = ignoredPathPrefixes; 21 | this.indexPage = "/".equals(indexPage) ? "" : indexPage; 22 | this.enableCompression = enableCompression; 23 | this.compressMediaTypes = compressMediaTypes; 24 | this.devServerDirectForwarding = devServerDirectForwarding; 25 | } 26 | 27 | @Override 28 | public boolean equals(Object o) { 29 | if (this == o) 30 | return true; 31 | if (o == null || getClass() != o.getClass()) 32 | return false; 33 | QuinoaDevProxyHandlerConfig that = (QuinoaDevProxyHandlerConfig) o; 34 | return enableCompression == that.enableCompression 35 | && devServerDirectForwarding == that.devServerDirectForwarding 36 | && Objects.equals(ignoredPathPrefixes, that.ignoredPathPrefixes) && Objects.equals(indexPage, that.indexPage) 37 | && Objects.equals(compressMediaTypes, that.compressMediaTypes); 38 | } 39 | 40 | @Override 41 | public int hashCode() { 42 | return Objects.hash(ignoredPathPrefixes, indexPage, enableCompression, compressMediaTypes, 43 | devServerDirectForwarding); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /runtime/src/main/java/io/quarkiverse/quinoa/QuinoaSPARoutingHandler.java: -------------------------------------------------------------------------------- 1 | package io.quarkiverse.quinoa; 2 | 3 | import static io.quarkiverse.quinoa.QuinoaRecorder.isIgnored; 4 | import static io.quarkiverse.quinoa.QuinoaRecorder.next; 5 | import static io.quarkiverse.quinoa.QuinoaRecorder.resolvePath; 6 | import static io.quarkiverse.quinoa.QuinoaRecorder.shouldHandleMethod; 7 | 8 | import java.util.List; 9 | import java.util.Objects; 10 | 11 | import org.jboss.logging.Logger; 12 | 13 | import io.vertx.core.Handler; 14 | import io.vertx.ext.web.RoutingContext; 15 | 16 | class QuinoaSPARoutingHandler implements Handler { 17 | private static final Logger LOG = Logger.getLogger(QuinoaSPARoutingHandler.class); 18 | private final ClassLoader currentClassLoader; 19 | private final List ignoredPathPrefixes; 20 | 21 | public QuinoaSPARoutingHandler(List ignoredPathPrefixes) { 22 | this.ignoredPathPrefixes = ignoredPathPrefixes; 23 | currentClassLoader = Thread.currentThread().getContextClassLoader(); 24 | } 25 | 26 | @Override 27 | public void handle(RoutingContext ctx) { 28 | if (!shouldHandleMethod(ctx)) { 29 | next(currentClassLoader, ctx); 30 | return; 31 | } 32 | String path = resolvePath(ctx); 33 | if (!Objects.equals(path, "/") && !isIgnored(path, ignoredPathPrefixes)) { 34 | String mountPoint = ctx.mountPoint() != null ? ctx.mountPoint() : "/"; 35 | String routePath = ctx.currentRoute().getPath() != null ? ctx.currentRoute().getPath() : "/"; 36 | String target; 37 | if (mountPoint.endsWith("/")) { 38 | target = mountPoint.substring(0, mountPoint.length() - 1) + routePath; 39 | } else { 40 | target = mountPoint + routePath; 41 | } 42 | LOG.debugf("Quinoa is re-routing SPA request '%s' to '%s'", ctx.normalizedPath(), target); 43 | ctx.reroute(target); 44 | } else { 45 | next(currentClassLoader, ctx); 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /runtime/src/main/resources/META-INF/quarkus-extension.yaml: -------------------------------------------------------------------------------- 1 | name: Quinoa 2 | metadata: 3 | keywords: 4 | - quinoa 5 | - ui 6 | - react 7 | - angular 8 | - vue 9 | - lit 10 | - svelte 11 | - astro 12 | - solidjs 13 | - emberjs 14 | - aurelia 15 | - polymer 16 | - spa 17 | - node 18 | - nodejs 19 | - npm 20 | - web 21 | - frontend 22 | guide: https://quarkiverse.github.io/quarkiverse-docs/quarkus-quinoa/dev/index.html 23 | icon-url: "https://raw.githubusercontent.com/quarkiverse/quarkus-quinoa/main/docs/modules/ROOT/assets/images/npm-logo.svg" 24 | categories: 25 | - "web" 26 | config: 27 | - "quarkus.quinoa." 28 | status: "stable" 29 | codestart: 30 | name: "quinoa" 31 | languages: 32 | - "java" 33 | - "kotlin" 34 | - "scala" 35 | artifact: "io.quarkiverse.quinoa:quarkus-quinoa:codestarts:jar:${project.version}" 36 | -------------------------------------------------------------------------------- /testing/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | 5 | io.quarkiverse.quinoa 6 | quarkus-quinoa-parent 7 | 999-SNAPSHOT 8 | 9 | quarkus-quinoa-testing 10 | Quarkus - Quinoa - Testing 11 | 12 | 13 | io.quarkiverse.playwright 14 | quarkus-playwright 15 | ${quarkus-playright.version} 16 | 17 | 18 | io.quarkus 19 | quarkus-junit5 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /testing/src/main/java/io/quarkiverse/quinoa/testing/QuinoaTestProfiles.java: -------------------------------------------------------------------------------- 1 | package io.quarkiverse.quinoa.testing; 2 | 3 | import java.util.Map; 4 | 5 | import io.quarkus.test.junit.QuarkusTestProfile; 6 | 7 | public class QuinoaTestProfiles { 8 | 9 | public static class Enable implements QuarkusTestProfile { 10 | @Override 11 | public Map getConfigOverrides() { 12 | return Map.of("quarkus.quinoa", "true"); 13 | } 14 | } 15 | 16 | public static class EnableAndRunTests implements QuarkusTestProfile { 17 | @Override 18 | public Map getConfigOverrides() { 19 | return Map.of( 20 | "quarkus.quinoa", "true", 21 | "quarkus.quinoa.run-tests", "true"); 22 | } 23 | } 24 | } 25 | --------------------------------------------------------------------------------