From fa80fac4534713ccd3842053fc55352c6a3853dd Mon Sep 17 00:00:00 2001 From: Marcelo Shima Date: Thu, 6 Jun 2024 22:10:51 -0300 Subject: [PATCH 1/6] add support to record videos (#1776) * enable video record * Update run-detox-tests.sh * Update ios.yml * adjusts * Update ios.yml * Update utils.js.ejs * Update ios.yml * Update utils.js.ejs * Update ios.yml --- .github/workflows/ios.yml | 3 +++ test/scripts/run-detox-tests.sh | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ios.yml b/.github/workflows/ios.yml index c7bbfa7db..1297c887e 100644 --- a/.github/workflows/ios.yml +++ b/.github/workflows/ios.yml @@ -134,6 +134,9 @@ jobs: if: steps.compare.outputs.equals != 'true' working-directory: ${{ github.workspace }}/backend - run: npm run e2e:test:ios + timeout-minutes: 15 + env: + DETOX_RECORD_VIDEOS: "${{ contains(github.event.pull_request.labels.*.name, 'pr: record-videos') && 'all' || 'none' }}" if: steps.compare.outputs.equals != 'true' - uses: actions/upload-artifact@v4 if: steps.compare.outputs.equals != 'true' && always() diff --git a/test/scripts/run-detox-tests.sh b/test/scripts/run-detox-tests.sh index ea3067130..a6b7eee1b 100755 --- a/test/scripts/run-detox-tests.sh +++ b/test/scripts/run-detox-tests.sh @@ -89,7 +89,7 @@ fi # run the detox tests if [ "$PLATFORM" = "ios" ]; then - npm run test:e2e -- --record-videos $DETOX_RECORD_VIDEO + npm run test:e2e else bash ${GITHUB_WORKSPACE}/${SCRIPT_DIR}/start-android-emulator.sh detox test --configuration android.emu.release From ed8a90823fbd929b4dc6353bb5d01509fa62530b Mon Sep 17 00:00:00 2001 From: Marcelo Shima Date: Fri, 7 Jun 2024 14:05:16 -0300 Subject: [PATCH 2/6] update husky dependencies (#1796) --- generators/react-native/generator.mjs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/generators/react-native/generator.mjs b/generators/react-native/generator.mjs index 833b8b269..6b5898e8b 100644 --- a/generators/react-native/generator.mjs +++ b/generators/react-native/generator.mjs @@ -166,6 +166,10 @@ export default class extends BaseApplicationGenerator { preparingPatchInFile() { this.patchInFile = patchInFile.bind(this); }, + husky({ application }) { + application.nodeDependencies.husky = '9.0.11'; + application.nodeDependencies['lint-staged'] = '15.2.5'; + }, }); } From 78748843897f3046803585192957520ff8a0ed69 Mon Sep 17 00:00:00 2001 From: Marcelo Shima Date: Fri, 7 Jun 2024 16:17:58 -0300 Subject: [PATCH 3/6] add spring-boot generator for cors customization (#1797) * add spring-boot generator for cors customization * adjust cors urls Co-authored-by: Matt Raible * more cors url adjusts Co-authored-by: Matt Raible --------- Co-authored-by: Matt Raible --- .../__snapshots__/generator.spec.mjs.snap | 567 ++++++++++++++++++ generators/spring-boot/generator.mjs | 40 ++ generators/spring-boot/generator.spec.mjs | 26 + generators/spring-boot/index.mjs | 1 + .../resources/config/application-e2e-cors.yml | 8 + 5 files changed, 642 insertions(+) create mode 100644 generators/spring-boot/__snapshots__/generator.spec.mjs.snap create mode 100644 generators/spring-boot/generator.mjs create mode 100644 generators/spring-boot/generator.spec.mjs create mode 100644 generators/spring-boot/index.mjs create mode 100644 generators/spring-boot/templates/src/main/resources/config/application-e2e-cors.yml diff --git a/generators/spring-boot/__snapshots__/generator.spec.mjs.snap b/generators/spring-boot/__snapshots__/generator.spec.mjs.snap new file mode 100644 index 000000000..aee1d3973 --- /dev/null +++ b/generators/spring-boot/__snapshots__/generator.spec.mjs.snap @@ -0,0 +1,567 @@ +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + +exports[`SubGenerator spring-boot of react-native JHipster blueprint > run > should succeed 1`] = ` +{ + ".devcontainer/Dockerfile": { + "stateCleared": "modified", + }, + ".devcontainer/devcontainer.json": { + "stateCleared": "modified", + }, + ".editorconfig": { + "stateCleared": "modified", + }, + ".gitattributes": { + "stateCleared": "modified", + }, + ".gitignore": { + "stateCleared": "modified", + }, + ".husky/pre-commit": { + "stateCleared": "modified", + }, + ".lintstagedrc.cjs": { + "stateCleared": "modified", + }, + ".mvn/jvm.config": { + "stateCleared": "modified", + }, + ".mvn/wrapper/maven-wrapper.jar": { + "stateCleared": "modified", + }, + ".mvn/wrapper/maven-wrapper.properties": { + "stateCleared": "modified", + }, + ".prettierignore": { + "stateCleared": "modified", + }, + ".prettierrc": { + "stateCleared": "modified", + }, + ".yo-rc.json": { + "stateCleared": "modified", + }, + "README.md": { + "stateCleared": "modified", + }, + "checkstyle.xml": { + "stateCleared": "modified", + }, + "mvnw": { + "stateCleared": "modified", + }, + "mvnw.cmd": { + "stateCleared": "modified", + }, + "npmw": { + "stateCleared": "modified", + }, + "npmw.cmd": { + "stateCleared": "modified", + }, + "package.json": { + "stateCleared": "modified", + }, + "pom.xml": { + "stateCleared": "modified", + }, + "sonar-project.properties": { + "stateCleared": "modified", + }, + "src/main/docker/app.yml": { + "stateCleared": "modified", + }, + "src/main/docker/grafana/provisioning/dashboards/JVM.json": { + "stateCleared": "modified", + }, + "src/main/docker/grafana/provisioning/dashboards/dashboard.yml": { + "stateCleared": "modified", + }, + "src/main/docker/grafana/provisioning/datasources/datasource.yml": { + "stateCleared": "modified", + }, + "src/main/docker/jhipster-control-center.yml": { + "stateCleared": "modified", + }, + "src/main/docker/jib/entrypoint.sh": { + "stateCleared": "modified", + }, + "src/main/docker/monitoring.yml": { + "stateCleared": "modified", + }, + "src/main/docker/postgresql.yml": { + "stateCleared": "modified", + }, + "src/main/docker/prometheus/prometheus.yml": { + "stateCleared": "modified", + }, + "src/main/docker/services.yml": { + "stateCleared": "modified", + }, + "src/main/docker/sonar.yml": { + "stateCleared": "modified", + }, + "src/main/java/com/mycompany/myapp/ApplicationWebXml.java": { + "stateCleared": "modified", + }, + "src/main/java/com/mycompany/myapp/GeneratedByJHipster.java": { + "stateCleared": "modified", + }, + "src/main/java/com/mycompany/myapp/JhipsterApp.java": { + "stateCleared": "modified", + }, + "src/main/java/com/mycompany/myapp/aop/logging/LoggingAspect.java": { + "stateCleared": "modified", + }, + "src/main/java/com/mycompany/myapp/aop/logging/package-info.java": { + "stateCleared": "modified", + }, + "src/main/java/com/mycompany/myapp/config/ApplicationProperties.java": { + "stateCleared": "modified", + }, + "src/main/java/com/mycompany/myapp/config/AsyncConfiguration.java": { + "stateCleared": "modified", + }, + "src/main/java/com/mycompany/myapp/config/CRLFLogConverter.java": { + "stateCleared": "modified", + }, + "src/main/java/com/mycompany/myapp/config/CacheConfiguration.java": { + "stateCleared": "modified", + }, + "src/main/java/com/mycompany/myapp/config/Constants.java": { + "stateCleared": "modified", + }, + "src/main/java/com/mycompany/myapp/config/DatabaseConfiguration.java": { + "stateCleared": "modified", + }, + "src/main/java/com/mycompany/myapp/config/DateTimeFormatConfiguration.java": { + "stateCleared": "modified", + }, + "src/main/java/com/mycompany/myapp/config/JacksonConfiguration.java": { + "stateCleared": "modified", + }, + "src/main/java/com/mycompany/myapp/config/LiquibaseConfiguration.java": { + "stateCleared": "modified", + }, + "src/main/java/com/mycompany/myapp/config/LoggingAspectConfiguration.java": { + "stateCleared": "modified", + }, + "src/main/java/com/mycompany/myapp/config/LoggingConfiguration.java": { + "stateCleared": "modified", + }, + "src/main/java/com/mycompany/myapp/config/SecurityConfiguration.java": { + "stateCleared": "modified", + }, + "src/main/java/com/mycompany/myapp/config/SecurityJwtConfiguration.java": { + "stateCleared": "modified", + }, + "src/main/java/com/mycompany/myapp/config/StaticResourcesWebConfiguration.java": { + "stateCleared": "modified", + }, + "src/main/java/com/mycompany/myapp/config/WebConfigurer.java": { + "stateCleared": "modified", + }, + "src/main/java/com/mycompany/myapp/config/package-info.java": { + "stateCleared": "modified", + }, + "src/main/java/com/mycompany/myapp/domain/AbstractAuditingEntity.java": { + "stateCleared": "modified", + }, + "src/main/java/com/mycompany/myapp/domain/Authority.java": { + "stateCleared": "modified", + }, + "src/main/java/com/mycompany/myapp/domain/User.java": { + "stateCleared": "modified", + }, + "src/main/java/com/mycompany/myapp/domain/package-info.java": { + "stateCleared": "modified", + }, + "src/main/java/com/mycompany/myapp/management/SecurityMetersService.java": { + "stateCleared": "modified", + }, + "src/main/java/com/mycompany/myapp/management/package-info.java": { + "stateCleared": "modified", + }, + "src/main/java/com/mycompany/myapp/package-info.java": { + "stateCleared": "modified", + }, + "src/main/java/com/mycompany/myapp/repository/AuthorityRepository.java": { + "stateCleared": "modified", + }, + "src/main/java/com/mycompany/myapp/repository/UserRepository.java": { + "stateCleared": "modified", + }, + "src/main/java/com/mycompany/myapp/repository/package-info.java": { + "stateCleared": "modified", + }, + "src/main/java/com/mycompany/myapp/security/AuthoritiesConstants.java": { + "stateCleared": "modified", + }, + "src/main/java/com/mycompany/myapp/security/DomainUserDetailsService.java": { + "stateCleared": "modified", + }, + "src/main/java/com/mycompany/myapp/security/SecurityUtils.java": { + "stateCleared": "modified", + }, + "src/main/java/com/mycompany/myapp/security/SpringSecurityAuditorAware.java": { + "stateCleared": "modified", + }, + "src/main/java/com/mycompany/myapp/security/UserNotActivatedException.java": { + "stateCleared": "modified", + }, + "src/main/java/com/mycompany/myapp/security/package-info.java": { + "stateCleared": "modified", + }, + "src/main/java/com/mycompany/myapp/service/EmailAlreadyUsedException.java": { + "stateCleared": "modified", + }, + "src/main/java/com/mycompany/myapp/service/InvalidPasswordException.java": { + "stateCleared": "modified", + }, + "src/main/java/com/mycompany/myapp/service/MailService.java": { + "stateCleared": "modified", + }, + "src/main/java/com/mycompany/myapp/service/UserService.java": { + "stateCleared": "modified", + }, + "src/main/java/com/mycompany/myapp/service/UsernameAlreadyUsedException.java": { + "stateCleared": "modified", + }, + "src/main/java/com/mycompany/myapp/service/dto/AdminUserDTO.java": { + "stateCleared": "modified", + }, + "src/main/java/com/mycompany/myapp/service/dto/PasswordChangeDTO.java": { + "stateCleared": "modified", + }, + "src/main/java/com/mycompany/myapp/service/dto/UserDTO.java": { + "stateCleared": "modified", + }, + "src/main/java/com/mycompany/myapp/service/dto/package-info.java": { + "stateCleared": "modified", + }, + "src/main/java/com/mycompany/myapp/service/mapper/UserMapper.java": { + "stateCleared": "modified", + }, + "src/main/java/com/mycompany/myapp/service/mapper/package-info.java": { + "stateCleared": "modified", + }, + "src/main/java/com/mycompany/myapp/service/package-info.java": { + "stateCleared": "modified", + }, + "src/main/java/com/mycompany/myapp/web/filter/SpaWebFilter.java": { + "stateCleared": "modified", + }, + "src/main/java/com/mycompany/myapp/web/filter/package-info.java": { + "stateCleared": "modified", + }, + "src/main/java/com/mycompany/myapp/web/rest/AccountResource.java": { + "stateCleared": "modified", + }, + "src/main/java/com/mycompany/myapp/web/rest/AuthenticateController.java": { + "stateCleared": "modified", + }, + "src/main/java/com/mycompany/myapp/web/rest/AuthorityResource.java": { + "stateCleared": "modified", + }, + "src/main/java/com/mycompany/myapp/web/rest/PublicUserResource.java": { + "stateCleared": "modified", + }, + "src/main/java/com/mycompany/myapp/web/rest/UserResource.java": { + "stateCleared": "modified", + }, + "src/main/java/com/mycompany/myapp/web/rest/errors/BadRequestAlertException.java": { + "stateCleared": "modified", + }, + "src/main/java/com/mycompany/myapp/web/rest/errors/EmailAlreadyUsedException.java": { + "stateCleared": "modified", + }, + "src/main/java/com/mycompany/myapp/web/rest/errors/ErrorConstants.java": { + "stateCleared": "modified", + }, + "src/main/java/com/mycompany/myapp/web/rest/errors/ExceptionTranslator.java": { + "stateCleared": "modified", + }, + "src/main/java/com/mycompany/myapp/web/rest/errors/FieldErrorVM.java": { + "stateCleared": "modified", + }, + "src/main/java/com/mycompany/myapp/web/rest/errors/InvalidPasswordException.java": { + "stateCleared": "modified", + }, + "src/main/java/com/mycompany/myapp/web/rest/errors/LoginAlreadyUsedException.java": { + "stateCleared": "modified", + }, + "src/main/java/com/mycompany/myapp/web/rest/errors/package-info.java": { + "stateCleared": "modified", + }, + "src/main/java/com/mycompany/myapp/web/rest/package-info.java": { + "stateCleared": "modified", + }, + "src/main/java/com/mycompany/myapp/web/rest/vm/KeyAndPasswordVM.java": { + "stateCleared": "modified", + }, + "src/main/java/com/mycompany/myapp/web/rest/vm/LoginVM.java": { + "stateCleared": "modified", + }, + "src/main/java/com/mycompany/myapp/web/rest/vm/ManagedUserVM.java": { + "stateCleared": "modified", + }, + "src/main/java/com/mycompany/myapp/web/rest/vm/package-info.java": { + "stateCleared": "modified", + }, + "src/main/resources/banner.txt": { + "stateCleared": "modified", + }, + "src/main/resources/config/application-dev.yml": { + "stateCleared": "modified", + }, + "src/main/resources/config/application-e2e-cors.yml": { + "stateCleared": "modified", + }, + "src/main/resources/config/application-prod.yml": { + "stateCleared": "modified", + }, + "src/main/resources/config/application-tls.yml": { + "stateCleared": "modified", + }, + "src/main/resources/config/application.yml": { + "stateCleared": "modified", + }, + "src/main/resources/config/liquibase/changelog/00000000000000_initial_schema.xml": { + "stateCleared": "modified", + }, + "src/main/resources/config/liquibase/data/authority.csv": { + "stateCleared": "modified", + }, + "src/main/resources/config/liquibase/data/user.csv": { + "stateCleared": "modified", + }, + "src/main/resources/config/liquibase/data/user_authority.csv": { + "stateCleared": "modified", + }, + "src/main/resources/config/liquibase/master.xml": { + "stateCleared": "modified", + }, + "src/main/resources/config/tls/keystore.p12": { + "stateCleared": "modified", + }, + "src/main/resources/i18n/messages.properties": { + "stateCleared": "modified", + }, + "src/main/resources/i18n/messages_en.properties": { + "stateCleared": "modified", + }, + "src/main/resources/logback-spring.xml": { + "stateCleared": "modified", + }, + "src/main/resources/templates/error.html": { + "stateCleared": "modified", + }, + "src/main/resources/templates/mail/activationEmail.html": { + "stateCleared": "modified", + }, + "src/main/resources/templates/mail/creationEmail.html": { + "stateCleared": "modified", + }, + "src/main/resources/templates/mail/passwordResetEmail.html": { + "stateCleared": "modified", + }, + "src/main/webapp/i18n/en/activate.json": { + "stateCleared": "modified", + }, + "src/main/webapp/i18n/en/adminAuthority.json": { + "stateCleared": "modified", + }, + "src/main/webapp/i18n/en/configuration.json": { + "stateCleared": "modified", + }, + "src/main/webapp/i18n/en/error.json": { + "stateCleared": "modified", + }, + "src/main/webapp/i18n/en/global.json": { + "stateCleared": "modified", + }, + "src/main/webapp/i18n/en/health.json": { + "stateCleared": "modified", + }, + "src/main/webapp/i18n/en/home.json": { + "stateCleared": "modified", + }, + "src/main/webapp/i18n/en/login.json": { + "stateCleared": "modified", + }, + "src/main/webapp/i18n/en/logs.json": { + "stateCleared": "modified", + }, + "src/main/webapp/i18n/en/metrics.json": { + "stateCleared": "modified", + }, + "src/main/webapp/i18n/en/password.json": { + "stateCleared": "modified", + }, + "src/main/webapp/i18n/en/register.json": { + "stateCleared": "modified", + }, + "src/main/webapp/i18n/en/reset.json": { + "stateCleared": "modified", + }, + "src/main/webapp/i18n/en/sessions.json": { + "stateCleared": "modified", + }, + "src/main/webapp/i18n/en/settings.json": { + "stateCleared": "modified", + }, + "src/main/webapp/i18n/en/user-management.json": { + "stateCleared": "modified", + }, + "src/test/java/com/mycompany/myapp/IntegrationTest.java": { + "stateCleared": "modified", + }, + "src/test/java/com/mycompany/myapp/TechnicalStructureTest.java": { + "stateCleared": "modified", + }, + "src/test/java/com/mycompany/myapp/config/AsyncSyncConfiguration.java": { + "stateCleared": "modified", + }, + "src/test/java/com/mycompany/myapp/config/CRLFLogConverterTest.java": { + "stateCleared": "modified", + }, + "src/test/java/com/mycompany/myapp/config/EmbeddedSQL.java": { + "stateCleared": "modified", + }, + "src/test/java/com/mycompany/myapp/config/PostgreSqlTestContainer.java": { + "stateCleared": "modified", + }, + "src/test/java/com/mycompany/myapp/config/SpringBootTestClassOrderer.java": { + "stateCleared": "modified", + }, + "src/test/java/com/mycompany/myapp/config/SqlTestContainer.java": { + "stateCleared": "modified", + }, + "src/test/java/com/mycompany/myapp/config/SqlTestContainersSpringContextCustomizerFactory.java": { + "stateCleared": "modified", + }, + "src/test/java/com/mycompany/myapp/config/StaticResourcesWebConfigurerTest.java": { + "stateCleared": "modified", + }, + "src/test/java/com/mycompany/myapp/config/WebConfigurerTest.java": { + "stateCleared": "modified", + }, + "src/test/java/com/mycompany/myapp/config/WebConfigurerTestController.java": { + "stateCleared": "modified", + }, + "src/test/java/com/mycompany/myapp/config/timezone/HibernateTimeZoneIT.java": { + "stateCleared": "modified", + }, + "src/test/java/com/mycompany/myapp/domain/AssertUtils.java": { + "stateCleared": "modified", + }, + "src/test/java/com/mycompany/myapp/domain/AuthorityAsserts.java": { + "stateCleared": "modified", + }, + "src/test/java/com/mycompany/myapp/domain/AuthorityTest.java": { + "stateCleared": "modified", + }, + "src/test/java/com/mycompany/myapp/domain/AuthorityTestSamples.java": { + "stateCleared": "modified", + }, + "src/test/java/com/mycompany/myapp/management/SecurityMetersServiceTests.java": { + "stateCleared": "modified", + }, + "src/test/java/com/mycompany/myapp/repository/timezone/DateTimeWrapper.java": { + "stateCleared": "modified", + }, + "src/test/java/com/mycompany/myapp/repository/timezone/DateTimeWrapperRepository.java": { + "stateCleared": "modified", + }, + "src/test/java/com/mycompany/myapp/security/DomainUserDetailsServiceIT.java": { + "stateCleared": "modified", + }, + "src/test/java/com/mycompany/myapp/security/SecurityUtilsUnitTest.java": { + "stateCleared": "modified", + }, + "src/test/java/com/mycompany/myapp/security/jwt/AuthenticationIntegrationTest.java": { + "stateCleared": "modified", + }, + "src/test/java/com/mycompany/myapp/security/jwt/JwtAuthenticationTestUtils.java": { + "stateCleared": "modified", + }, + "src/test/java/com/mycompany/myapp/security/jwt/TokenAuthenticationIT.java": { + "stateCleared": "modified", + }, + "src/test/java/com/mycompany/myapp/security/jwt/TokenAuthenticationSecurityMetersIT.java": { + "stateCleared": "modified", + }, + "src/test/java/com/mycompany/myapp/service/MailServiceIT.java": { + "stateCleared": "modified", + }, + "src/test/java/com/mycompany/myapp/service/UserServiceIT.java": { + "stateCleared": "modified", + }, + "src/test/java/com/mycompany/myapp/service/mapper/UserMapperTest.java": { + "stateCleared": "modified", + }, + "src/test/java/com/mycompany/myapp/web/filter/SpaWebFilterIT.java": { + "stateCleared": "modified", + }, + "src/test/java/com/mycompany/myapp/web/rest/AccountResourceIT.java": { + "stateCleared": "modified", + }, + "src/test/java/com/mycompany/myapp/web/rest/AuthenticateControllerIT.java": { + "stateCleared": "modified", + }, + "src/test/java/com/mycompany/myapp/web/rest/AuthorityResourceIT.java": { + "stateCleared": "modified", + }, + "src/test/java/com/mycompany/myapp/web/rest/PublicUserResourceIT.java": { + "stateCleared": "modified", + }, + "src/test/java/com/mycompany/myapp/web/rest/TestUtil.java": { + "stateCleared": "modified", + }, + "src/test/java/com/mycompany/myapp/web/rest/UserResourceIT.java": { + "stateCleared": "modified", + }, + "src/test/java/com/mycompany/myapp/web/rest/WithUnauthenticatedMockUser.java": { + "stateCleared": "modified", + }, + "src/test/java/com/mycompany/myapp/web/rest/errors/ExceptionTranslatorIT.java": { + "stateCleared": "modified", + }, + "src/test/java/com/mycompany/myapp/web/rest/errors/ExceptionTranslatorTestController.java": { + "stateCleared": "modified", + }, + "src/test/resources/META-INF/spring.factories": { + "stateCleared": "modified", + }, + "src/test/resources/config/application-testdev.yml": { + "stateCleared": "modified", + }, + "src/test/resources/config/application-testprod.yml": { + "stateCleared": "modified", + }, + "src/test/resources/config/application.yml": { + "stateCleared": "modified", + }, + "src/test/resources/i18n/messages_en.properties": { + "stateCleared": "modified", + }, + "src/test/resources/junit-platform.properties": { + "stateCleared": "modified", + }, + "src/test/resources/logback.xml": { + "stateCleared": "modified", + }, + "src/test/resources/templates/mail/activationEmail.html": { + "stateCleared": "modified", + }, + "src/test/resources/templates/mail/creationEmail.html": { + "stateCleared": "modified", + }, + "src/test/resources/templates/mail/passwordResetEmail.html": { + "stateCleared": "modified", + }, + "src/test/resources/templates/mail/testEmail.html": { + "stateCleared": "modified", + }, +} +`; diff --git a/generators/spring-boot/generator.mjs b/generators/spring-boot/generator.mjs new file mode 100644 index 000000000..14af5b796 --- /dev/null +++ b/generators/spring-boot/generator.mjs @@ -0,0 +1,40 @@ +import BaseApplicationGenerator from 'generator-jhipster/generators/base-application'; + +export default class extends BaseApplicationGenerator { + constructor(args, opts, features) { + super(args, opts, { ...features, sbsBlueprint: true }); + } + + get [BaseApplicationGenerator.WRITING]() { + return this.asWritingTaskGroup({ + async writingTemplateTask({ application }) { + await this.writeFiles({ + templates: [ + { + sourceFile: 'src/main/resources/config/application-e2e-cors.yml', + destinationFile: 'src/main/resources/config/application-e2e-cors.yml', + noEjs: true, + }, + ], + context: application, + }); + }, + }); + } + + get [BaseApplicationGenerator.POST_WRITING]() { + return this.asPostWritingTaskGroup({ + async postWritingTemplateTask() { + this.editFile('src/main/docker/app.yml', content => + content.replace('SPRING_PROFILES_ACTIVE=prod,api-docs', 'SPRING_PROFILES_ACTIVE=prod,api-docs,e2e-cors'), + ); + this.editFile('src/main/resources/config/application.yml', content => + content.replace(/allowed-origins: (['"])(.*)['"]/, 'allowed-origins: $1$2,http://localhost:8081,http://localhost$1'), + ); + this.editFile('src/main/resources/config/application-dev.yml', content => + content.replace(/allowed-origins: (['"])(.*)['"]/, 'allowed-origins: $1$2,http://localhost:8081,http://localhost$1'), + ); + }, + }); + } +} diff --git a/generators/spring-boot/generator.spec.mjs b/generators/spring-boot/generator.spec.mjs new file mode 100644 index 000000000..0f993c060 --- /dev/null +++ b/generators/spring-boot/generator.spec.mjs @@ -0,0 +1,26 @@ +import { beforeAll, describe, expect, it } from 'vitest'; + +import { defaultHelpers as helpers, result } from 'generator-jhipster/testing'; + +const SUB_GENERATOR = 'spring-boot'; +const BLUEPRINT_NAMESPACE = `jhipster:${SUB_GENERATOR}`; + +describe('SubGenerator spring-boot of react-native JHipster blueprint', () => { + describe('run', () => { + beforeAll(async function () { + await helpers + .run(BLUEPRINT_NAMESPACE) + .withJHipsterConfig() + .withOptions({ + ignoreNeedlesError: true, + blueprint: 'react-native', + }) + .withJHipsterLookup() + .withParentBlueprintLookup(); + }); + + it('should succeed', () => { + expect(result.getStateSnapshot()).toMatchSnapshot(); + }); + }); +}); diff --git a/generators/spring-boot/index.mjs b/generators/spring-boot/index.mjs new file mode 100644 index 000000000..adaf4ca2e --- /dev/null +++ b/generators/spring-boot/index.mjs @@ -0,0 +1 @@ +export { default } from './generator.mjs'; diff --git a/generators/spring-boot/templates/src/main/resources/config/application-e2e-cors.yml b/generators/spring-boot/templates/src/main/resources/config/application-e2e-cors.yml new file mode 100644 index 000000000..22567c5ca --- /dev/null +++ b/generators/spring-boot/templates/src/main/resources/config/application-e2e-cors.yml @@ -0,0 +1,8 @@ +jhipster: + cors: + allowed-origins: "http://localhost:8081,http://localhost" + allowed-methods: "*" + allowed-headers: "*" + exposed-headers: "Authorization,Link,X-Total-Count,X-${jhipster.clientApp.name}-alert,X-${jhipster.clientApp.name}-error,X-${jhipster.clientApp.name}-params" + allow-credentials: true + max-age: 1800 From 4a98bf814cdd01b82f8738b553eded6f738b6a7e Mon Sep 17 00:00:00 2001 From: Matt Raible Date: Fri, 7 Jun 2024 13:18:17 -0600 Subject: [PATCH 4/6] Fix OAuth authentication (#1794) * Fix OAuth authentication * Simplify OAuth login with PKCE * Remove workaround * Fix quotes --- .../app/modules/login/login.utils.ts.ejs | 58 ++++++++----------- 1 file changed, 24 insertions(+), 34 deletions(-) diff --git a/generators/react-native/templates/app/modules/login/login.utils.ts.ejs b/generators/react-native/templates/app/modules/login/login.utils.ts.ejs index 4cefda50a..a5b3b7cbd 100644 --- a/generators/react-native/templates/app/modules/login/login.utils.ts.ejs +++ b/generators/react-native/templates/app/modules/login/login.utils.ts.ejs @@ -1,41 +1,12 @@ import { Platform } from 'react-native'; -import { DiscoveryDocument, makeRedirectUri } from 'expo-auth-session'; +import { AuthRequest, AuthSessionResult, DiscoveryDocument, makeRedirectUri } from 'expo-auth-session'; import * as AuthSession from 'expo-auth-session'; -import { generateHexStringAsync, buildCodeAsync } from 'expo-auth-session/src/PKCE'; -import { buildQueryString } from 'expo-auth-session/src/QueryParams'; import * as WebBrowser from 'expo-web-browser'; import * as Linking from 'expo-linking'; import AppConfig from '../../config/app-config'; WebBrowser.maybeCompleteAuthSession(); -interface AuthParams { - state: string; - codeVerifier: string; - authUrl: string; -} - -export async function getAuthParams(clientId: string, redirectUri: string, discovery: DiscoveryDocument): Promise { - const state = await generateHexStringAsync(16); - const { codeVerifier, codeChallenge } = await buildCodeAsync(); - const authenticationOptions = { - response_type: 'code', - code_challenge: codeChallenge, - code_challenge_method: 'S256', - scope: ['openid', 'profile', 'email', 'address', 'phone', 'offline_access'].join(' '), - state, - client_id: clientId, - redirect_uri: redirectUri, - audience: 'api://default', - }; - const authUrl = `${discovery.discoveryDocument?.authorization_endpoint}?${buildQueryString(authenticationOptions)}`; - return { - state, - codeVerifier, - authUrl, - }; -} - export async function exchangeCodeForToken( clientId: string, redirectUri: string, @@ -63,24 +34,40 @@ export function extractCodeOrThrow(result: AuthSession.AuthSessionResult, state: throw result; } } + export async function getDiscovery(issuer: string): Promise { return AuthSession.fetchDiscoveryAsync(issuer); } +export function generateShortUUID() { + return Math.random().toString(36).substring(2, 15); +} + export async function doOauthPkceFlow(clientId: string, issuer: string): Promise { // set up redirect uri const redirectUri = makeRedirectUri({ useProxy: AppConfig.useExpoAuthProxy }); // fetch oauth issuer information from discovery endpoint const discovery = await getDiscovery(issuer); // set up the IDP url, prepare codeVerifier and state - const { authUrl, codeVerifier, state } = await getAuthParams(clientId, redirectUri, discovery); // redirect to the IDP const returnUri = Platform.OS === 'android' && !AppConfig.useExpoAuthProxy ? redirectUri : Linking.createURL('/'); - const authResult = await AuthSession.startAsync({ authUrl, returnUrl: returnUri }); + const state = generateShortUUID(); + // Get Authorization code + const authRequestOptions: AuthSession.AuthRequestConfig = { + responseType: AuthSession.ResponseType.Code, + clientId, + redirectUri: returnUri, + prompt: AuthSession.Prompt.Login, + scopes: ['openid', 'profile', 'email', 'address', 'phone', 'offline_access'], + state, + usePKCE: true, + }; + const authRequest: AuthRequest = new AuthSession.AuthRequest(authRequestOptions); + const authResult: AuthSessionResult = await authRequest.promptAsync(discovery, { useProxy: AppConfig.useExpoAuthProxy }); // check the response for success/failure const code = extractCodeOrThrow(authResult, state); // exchange the received code for an access token - return exchangeCodeForToken(clientId, redirectUri, discovery, code, codeVerifier); + return exchangeCodeForToken(clientId, returnUri, discovery, code, authRequest.codeVerifier || ''); } export async function logoutFromIdp(clientId: string, issuer: string, idToken: string) { @@ -91,7 +78,10 @@ export async function logoutFromIdp(clientId: string, issuer: string, idToken: s if (endSessionEndpoint) { // set up redirect uri const redirectUri = makeRedirectUri({ useProxy: AppConfig.useExpoAuthProxy }); - await WebBrowser.openAuthSessionAsync(`${endSessionEndpoint}?id_token_hint=${idToken}&client_id=${clientId}&post_logout_redirect_uri=${redirectUri}`, redirectUri); + await WebBrowser.openAuthSessionAsync( + `${endSessionEndpoint}?id_token_hint=${idToken}&client_id=${clientId}&post_logout_redirect_uri=${redirectUri}`, + redirectUri, + ); } else if (issuer.includes('auth0.com')) { // Auth0 need special handling since end_session_endpoint is not in oidc-configuration const redirectUri = makeRedirectUri({ useProxy: AppConfig.useExpoAuthProxy }); From 690bd85ffea52cba935d81b855b0fc1e4bcd7cf3 Mon Sep 17 00:00:00 2001 From: Marcelo Shima Date: Fri, 7 Jun 2024 16:18:53 -0300 Subject: [PATCH 5/6] Storybook v7 (#1789) * Bump the storybook group across 1 directory with 3 updates Bumps the storybook group with 3 updates in the /generators/react-native/templates directory: [@storybook/addons](https://github.com/storybookjs/storybook/tree/HEAD/code/deprecated/addons), [@storybook/react-native](https://github.com/storybookjs/react-native/tree/HEAD/packages/react-native) and [@storybook/theming](https://github.com/storybookjs/storybook/tree/HEAD/code/lib/theming). Updates `@storybook/addons` from 7.6.13 to 7.6.17 - [Release notes](https://github.com/storybookjs/storybook/releases) - [Changelog](https://github.com/storybookjs/storybook/blob/v7.6.17/CHANGELOG.md) - [Commits](https://github.com/storybookjs/storybook/commits/v7.6.17/code/deprecated/addons) Updates `@storybook/react-native` from 6.5.7 to 7.6.19 - [Release notes](https://github.com/storybookjs/react-native/releases) - [Changelog](https://github.com/storybookjs/react-native/blob/next/CHANGELOG.md) - [Commits](https://github.com/storybookjs/react-native/commits/v7.6.19/packages/react-native) Updates `@storybook/theming` from 7.6.17 to 8.1.6 - [Release notes](https://github.com/storybookjs/storybook/releases) - [Changelog](https://github.com/storybookjs/storybook/blob/next/CHANGELOG.md) - [Commits](https://github.com/storybookjs/storybook/commits/v8.1.6/code/lib/theming) --- updated-dependencies: - dependency-name: "@storybook/addons" dependency-type: direct:development update-type: version-update:semver-patch dependency-group: storybook - dependency-name: "@storybook/react-native" dependency-type: direct:development update-type: version-update:semver-major dependency-group: storybook - dependency-name: "@storybook/theming" dependency-type: direct:development update-type: version-update:semver-major dependency-group: storybook ... Signed-off-by: dependabot[bot] * storybook migration * adjust to @storybook/react-native --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Matt Raible --- .../components/alert-message/alert-message.story.js.ejs | 2 +- .../app/shared/components/form/jhi-form-field.story.js.ejs | 2 +- .../components/rounded-button/rounded-button.story.js.ejs | 2 +- .../shared/components/search-bar/search-bar.story.js.ejs | 2 +- generators/react-native/templates/package.json | 6 +++--- generators/react-native/templates/storybook/index.js.ejs | 2 +- 6 files changed, 8 insertions(+), 8 deletions(-) diff --git a/generators/react-native/templates/app/shared/components/alert-message/alert-message.story.js.ejs b/generators/react-native/templates/app/shared/components/alert-message/alert-message.story.js.ejs index 4d04d986f..33dc650e9 100644 --- a/generators/react-native/templates/app/shared/components/alert-message/alert-message.story.js.ejs +++ b/generators/react-native/templates/app/shared/components/alert-message/alert-message.story.js.ejs @@ -1,5 +1,5 @@ import React from 'react' -import { storiesOf } from '@storybook/react-native' +import { storiesOf } from '@storybook/react-native/V6' import { StyleSheet } from 'react-native' import AlertMessage from './alert-message' diff --git a/generators/react-native/templates/app/shared/components/form/jhi-form-field.story.js.ejs b/generators/react-native/templates/app/shared/components/form/jhi-form-field.story.js.ejs index 762c71e86..00235367d 100644 --- a/generators/react-native/templates/app/shared/components/form/jhi-form-field.story.js.ejs +++ b/generators/react-native/templates/app/shared/components/form/jhi-form-field.story.js.ejs @@ -1,5 +1,5 @@ import React, { createRef } from 'react'; -import { storiesOf } from '@storybook/react-native'; +import { storiesOf } from '@storybook/react-native/V6'; import { View, StyleSheet, Text } from 'react-native'; import FormButton from './jhi-form-button'; import FormField from './jhi-form-field'; diff --git a/generators/react-native/templates/app/shared/components/rounded-button/rounded-button.story.js.ejs b/generators/react-native/templates/app/shared/components/rounded-button/rounded-button.story.js.ejs index c6ec565aa..fc5f5bb74 100644 --- a/generators/react-native/templates/app/shared/components/rounded-button/rounded-button.story.js.ejs +++ b/generators/react-native/templates/app/shared/components/rounded-button/rounded-button.story.js.ejs @@ -1,5 +1,5 @@ import React from 'react' -import { storiesOf } from '@storybook/react-native' +import { storiesOf } from '@storybook/react-native/V6' import RoundedButton from './rounded-button' diff --git a/generators/react-native/templates/app/shared/components/search-bar/search-bar.story.js.ejs b/generators/react-native/templates/app/shared/components/search-bar/search-bar.story.js.ejs index 7b7d278d3..8a5aebef5 100644 --- a/generators/react-native/templates/app/shared/components/search-bar/search-bar.story.js.ejs +++ b/generators/react-native/templates/app/shared/components/search-bar/search-bar.story.js.ejs @@ -1,6 +1,6 @@ import React from 'react' import { StyleSheet, View } from 'react-native' -import { storiesOf } from '@storybook/react-native' +import { storiesOf } from '@storybook/react-native/V6' import SearchBar from './search-bar' diff --git a/generators/react-native/templates/package.json b/generators/react-native/templates/package.json index ed56fa638..3295c52d0 100644 --- a/generators/react-native/templates/package.json +++ b/generators/react-native/templates/package.json @@ -36,9 +36,9 @@ "@config-plugins/detox": "6.0.0", "@react-native-community/eslint-config": "3.2.0", "@redux-devtools/extension": "3.3.0", - "@storybook/addons": "7.6.13", - "@storybook/react-native": "6.5.7", - "@storybook/theming": "7.6.17", + "@storybook/addons": "7.6.17", + "@storybook/react-native": "7.6.19", + "@storybook/theming": "8.1.6", "@testing-library/jest-native": "5.4.3", "@testing-library/react-native": "12.5.1", "@types/jest": "29.5.12", diff --git a/generators/react-native/templates/storybook/index.js.ejs b/generators/react-native/templates/storybook/index.js.ejs index 503db620d..6c3b5c894 100644 --- a/generators/react-native/templates/storybook/index.js.ejs +++ b/generators/react-native/templates/storybook/index.js.ejs @@ -1,4 +1,4 @@ -import { getStorybookUI, configure } from '@storybook/react-native' +import { getStorybookUI, configure } from '@storybook/react-native/V6' import { View } from 'react-native' import AsyncStorage from '@react-native-async-storage/async-storage'; import AppConfig from '../app/config/app-config'; From a1f35165f805416ceeda6816c68630ca5b8bf54f Mon Sep 17 00:00:00 2001 From: Marcelo Shima Date: Sun, 9 Jun 2024 13:53:52 -0300 Subject: [PATCH 6/6] fix detox e2e tests for entities (#1650) * try to enable e2e test at entities * Update utils.js.ejs * Update _entityFile_.spec.js.ejs * Update _entityFile_.spec.js.ejs * Update utils.js.ejs * Update utils.js.ejs * Update _entityFile_.spec.js.ejs * try to enable e2e with dates --- .../templates/e2e/entities/_entityFile_.spec.js.ejs | 4 ++-- generators/react-native/templates/e2e/utils.js.ejs | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/generators/react-native/templates/e2e/entities/_entityFile_.spec.js.ejs b/generators/react-native/templates/e2e/entities/_entityFile_.spec.js.ejs index 6cb746387..2b1e52c8f 100644 --- a/generators/react-native/templates/e2e/entities/_entityFile_.spec.js.ejs +++ b/generators/react-native/templates/e2e/entities/_entityFile_.spec.js.ejs @@ -1,5 +1,5 @@ <%_ if (anyFieldIsDateDerived) { _%> -const jestExpect = require('expect'); +const { expect: jestExpect } = require('expect'); <%_ } _%> const { reloadApp, @@ -51,7 +51,7 @@ Date.prototype.toCustomLocalDate = function() { } _%> -describe.skip('<%= entityNameCapitalized %> Screen Tests', () => { +describe<%- authenticationTypeOauth2 || anyFieldIsBlobDerived ? '.skip' : '' %>('<%= entityNameCapitalized %> Screen Tests', () => { beforeEach(async () => { await reloadApp(); await loginAsUser(); diff --git a/generators/react-native/templates/e2e/utils.js.ejs b/generators/react-native/templates/e2e/utils.js.ejs index 370210d2b..acb764ad6 100644 --- a/generators/react-native/templates/e2e/utils.js.ejs +++ b/generators/react-native/templates/e2e/utils.js.ejs @@ -81,7 +81,7 @@ const toggleSwitchToValue = async (switchId, targetValue) => { const scrollTo = async (fieldId, listId, size = 0.15, direction = 'up', speed = 'slow') => { await waitFor(element(by.id(fieldId))) .toBeVisible() - .whileElement(by.type('ABI49_0_0RCTScrollView').withAncestor(by.id(listId))) + .whileElement(by.id(listId)) .scroll(500, 'down'); }; @@ -144,6 +144,7 @@ const reloadApp = async (bailOnFailure) => { newInstance: true, launchArgs: { detoxEnableSynchronization: false, + permissions: { camera: 'YES', photo: 'YES' }, // Don't show developer menu. EXKernelDisableNuxDefaultsKey: true, },