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/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'; + }, }); } 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 }); 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, }, 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 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