diff --git a/src/main/java/tech/jhipster/lite/generator/client/vite/vue/core/application/ViteVueApplicationService.java b/src/main/java/tech/jhipster/lite/generator/client/vite/vue/core/application/ViteVueApplicationService.java new file mode 100644 index 00000000000..9fa947b5c89 --- /dev/null +++ b/src/main/java/tech/jhipster/lite/generator/client/vite/vue/core/application/ViteVueApplicationService.java @@ -0,0 +1,19 @@ +package tech.jhipster.lite.generator.client.vite.vue.core.application; + +import org.springframework.stereotype.Service; +import tech.jhipster.lite.generator.client.vite.vue.core.domain.ViteVueService; +import tech.jhipster.lite.generator.project.domain.Project; + +@Service +public class ViteVueApplicationService { + + private final ViteVueService viteVueService; + + public ViteVueApplicationService(ViteVueService viteVueService) { + this.viteVueService = viteVueService; + } + + public void addViteVue(Project project) { + viteVueService.addViteVue(project); + } +} diff --git a/src/main/java/tech/jhipster/lite/generator/client/vite/vue/core/domain/ViteVue.java b/src/main/java/tech/jhipster/lite/generator/client/vite/vue/core/domain/ViteVue.java new file mode 100644 index 00000000000..ed9fcf0eecc --- /dev/null +++ b/src/main/java/tech/jhipster/lite/generator/client/vite/vue/core/domain/ViteVue.java @@ -0,0 +1,34 @@ +package tech.jhipster.lite.generator.client.vite.vue.core.domain; + +import java.util.List; + +public class ViteVue { + + private ViteVue() {} + + public static List dependencies() { + return List.of("vue", "vue-class-component"); + } + + public static List devDependencies() { + return List.of( + "@rushstack/eslint-patch", + "@types/jest", + "@typescript-eslint/parser", + "@vitejs/plugin-vue", + "@vue/eslint-config-typescript", + "@vue/test-utils", + "eslint", + "eslint-config-prettier", + "eslint-plugin-vue", + "jest", + "jest-sonar-reporter", + "jest-transform-stub", + "ts-jest", + "typescript", + "vite", + "vue-jest", + "vue-tsc" + ); + } +} diff --git a/src/main/java/tech/jhipster/lite/generator/client/vite/vue/core/domain/ViteVueDomainService.java b/src/main/java/tech/jhipster/lite/generator/client/vite/vue/core/domain/ViteVueDomainService.java new file mode 100644 index 00000000000..584ddbf53d2 --- /dev/null +++ b/src/main/java/tech/jhipster/lite/generator/client/vite/vue/core/domain/ViteVueDomainService.java @@ -0,0 +1,127 @@ +package tech.jhipster.lite.generator.client.vite.vue.core.domain; + +import static tech.jhipster.lite.common.domain.FileUtils.getPath; +import static tech.jhipster.lite.generator.project.domain.Constants.PACKAGE_JSON; + +import java.util.List; +import java.util.Map; +import tech.jhipster.lite.error.domain.GeneratorException; +import tech.jhipster.lite.generator.packagemanager.npm.domain.NpmService; +import tech.jhipster.lite.generator.project.domain.Project; +import tech.jhipster.lite.generator.project.domain.ProjectRepository; + +public class ViteVueDomainService implements ViteVueService { + + public static final String SOURCE = "client/vite/vue3"; + + private final ProjectRepository projectRepository; + private final NpmService npmService; + + public ViteVueDomainService(ProjectRepository projectRepository, NpmService npmService) { + this.projectRepository = projectRepository; + this.npmService = npmService; + } + + @Override + public void addViteVue(Project project) { + addDependencies(project); + addDevDependencies(project); + addScripts(project); + addJestSonar(project); + + addViteConfigFiles(project); + + addRootFiles(project); + addAppFiles(project); + } + + public void addDependencies(Project project) { + ViteVue.dependencies().forEach(dependency -> addDependency(project, dependency)); + } + + public void addDevDependencies(Project project) { + ViteVue.devDependencies().forEach(devDependency -> addDevDependency(project, devDependency)); + } + + private void addDependency(Project project, String dependency) { + npmService + .getVersion("vite/vue3", dependency) + .ifPresentOrElse( + version -> npmService.addDependency(project, dependency, version), + () -> { + throw new GeneratorException("Dependency not found: " + dependency); + } + ); + } + + private void addDevDependency(Project project, String devDependency) { + npmService + .getVersion("vite/vue3", devDependency) + .ifPresentOrElse( + version -> npmService.addDevDependency(project, devDependency, version), + () -> { + throw new GeneratorException("DevDependency not found: " + devDependency); + } + ); + } + + public void addScripts(Project project) { + // prettier-ignore + Map + .of( + "build", "vue-tsc --noEmit && vite build --emptyOutDir", + "dev", "vite", + "preview", "vite preview", + "test", "jest src/test/javascript/spec" + ) + .forEach((name, cmd) -> npmService.addScript(project, name, cmd)); + } + + public void addViteConfigFiles(Project project) { + List + .of(".eslintrc.js", "jest.config.js", "tsconfig.json", "vite.config.ts") + .forEach(file -> projectRepository.add(project, SOURCE, file)); + } + + public void addRootFiles(Project project) { + projectRepository.template(project, getPath(SOURCE, "webapp"), "index.html", "src/main/webapp"); + projectRepository.template(project, getPath(SOURCE, "webapp/app"), "env.d.ts", "src/main/webapp/app"); + projectRepository.template(project, getPath(SOURCE, "webapp/app"), "main.ts", "src/main/webapp/app"); + + projectRepository.add( + project, + getPath(SOURCE, "webapp/content/images"), + "JHipster-Lite-neon-green.png", + "src/main/webapp/content/images" + ); + projectRepository.add(project, getPath(SOURCE, "webapp/content/images"), "logo.png", "src/main/webapp/content/images"); + } + + public void addAppFiles(Project project) { + String sourcePrimary = getPath(SOURCE, "webapp/app/common/primary/app"); + String destinationPrimary = "src/main/webapp/app/common/primary/app"; + + projectRepository.template(project, sourcePrimary, "App.component.ts", destinationPrimary); + projectRepository.template(project, sourcePrimary, "App.vue", destinationPrimary); + projectRepository.template(project, sourcePrimary, "index.ts", destinationPrimary); + + projectRepository.template( + project, + getPath(SOURCE, "test/spec/common/primary/app"), + "App.spec.ts", + "src/test/javascript/spec/common/primary/app" + ); + } + + public void addJestSonar(Project project) { + String oldText = "\"cacheDirectories\": \\["; + String newText = + """ + "jestSonar": \\{ + "reportPath": "target/test-results/jest", + "reportFile": "TESTS-results-sonar.xml" + \\}, + "cacheDirectories": \\["""; + projectRepository.replaceText(project, "", PACKAGE_JSON, oldText, newText); + } +} diff --git a/src/main/java/tech/jhipster/lite/generator/client/vite/vue/core/domain/ViteVueService.java b/src/main/java/tech/jhipster/lite/generator/client/vite/vue/core/domain/ViteVueService.java new file mode 100644 index 00000000000..433ecd7e3cf --- /dev/null +++ b/src/main/java/tech/jhipster/lite/generator/client/vite/vue/core/domain/ViteVueService.java @@ -0,0 +1,7 @@ +package tech.jhipster.lite.generator.client.vite.vue.core.domain; + +import tech.jhipster.lite.generator.project.domain.Project; + +public interface ViteVueService { + void addViteVue(Project project); +} diff --git a/src/main/java/tech/jhipster/lite/generator/client/vite/vue/core/infrastructure/config/ViteVueBeanConfiguration.java b/src/main/java/tech/jhipster/lite/generator/client/vite/vue/core/infrastructure/config/ViteVueBeanConfiguration.java new file mode 100644 index 00000000000..bb38176d441 --- /dev/null +++ b/src/main/java/tech/jhipster/lite/generator/client/vite/vue/core/infrastructure/config/ViteVueBeanConfiguration.java @@ -0,0 +1,25 @@ +package tech.jhipster.lite.generator.client.vite.vue.core.infrastructure.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import tech.jhipster.lite.generator.client.vite.vue.core.domain.ViteVueDomainService; +import tech.jhipster.lite.generator.client.vite.vue.core.domain.ViteVueService; +import tech.jhipster.lite.generator.packagemanager.npm.domain.NpmService; +import tech.jhipster.lite.generator.project.domain.ProjectRepository; + +@Configuration +public class ViteVueBeanConfiguration { + + private final ProjectRepository projectRepository; + private final NpmService npmService; + + public ViteVueBeanConfiguration(ProjectRepository projectRepository, NpmService npmService) { + this.projectRepository = projectRepository; + this.npmService = npmService; + } + + @Bean + public ViteVueService viteVueService() { + return new ViteVueDomainService(projectRepository, npmService); + } +} diff --git a/src/main/java/tech/jhipster/lite/generator/client/vite/vue/core/infrastructure/primary/rest/ViveVueResource.java b/src/main/java/tech/jhipster/lite/generator/client/vite/vue/core/infrastructure/primary/rest/ViveVueResource.java new file mode 100644 index 00000000000..d9dfe366826 --- /dev/null +++ b/src/main/java/tech/jhipster/lite/generator/client/vite/vue/core/infrastructure/primary/rest/ViveVueResource.java @@ -0,0 +1,34 @@ +package tech.jhipster.lite.generator.client.vite.vue.core.infrastructure.primary.rest; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import tech.jhipster.lite.generator.client.vite.vue.core.application.ViteVueApplicationService; +import tech.jhipster.lite.generator.project.domain.Project; +import tech.jhipster.lite.generator.project.infrastructure.primary.dto.ProjectDTO; +import tech.jhipster.lite.technical.infrastructure.primary.annotation.GeneratorStep; + +@RestController +@RequestMapping("/api/vite/vue") +@Tag(name = "Vite - Vue") +class ViveVueResource { + + private final ViteVueApplicationService viteVueApplicationService; + + public ViveVueResource(ViteVueApplicationService viteVueApplicationService) { + this.viteVueApplicationService = viteVueApplicationService; + } + + @Operation(summary = "Add Vite+Vue3", description = "Add Vite+Vue3") + @ApiResponse(responseCode = "500", description = "An error occurred while adding Vite+Vue3") + @PostMapping + @GeneratorStep(id = "vite-vue") + public void addViteVue(@RequestBody ProjectDTO projectDTO) { + Project project = ProjectDTO.toProject(projectDTO); + viteVueApplicationService.addViteVue(project); + } +} diff --git a/src/main/java/tech/jhipster/lite/generator/client/vite/vue/core/package-info.java b/src/main/java/tech/jhipster/lite/generator/client/vite/vue/core/package-info.java new file mode 100644 index 00000000000..417b06587a2 --- /dev/null +++ b/src/main/java/tech/jhipster/lite/generator/client/vite/vue/core/package-info.java @@ -0,0 +1,2 @@ +@tech.jhipster.lite.BusinessContext +package tech.jhipster.lite.generator.client.vite.vue.core; diff --git a/src/main/java/tech/jhipster/lite/generator/packagemanager/npm/domain/NpmDomainService.java b/src/main/java/tech/jhipster/lite/generator/packagemanager/npm/domain/NpmDomainService.java index f856e5e7efc..60e532e34f2 100644 --- a/src/main/java/tech/jhipster/lite/generator/packagemanager/npm/domain/NpmDomainService.java +++ b/src/main/java/tech/jhipster/lite/generator/packagemanager/npm/domain/NpmDomainService.java @@ -75,11 +75,12 @@ public Optional getVersionInCommon(String name) { return getVersion("common", name); } - private Optional getVersion(String folderType, String name) { - Assert.notBlank("folderType", folderType); + @Override + public Optional getVersion(String folder, String name) { + Assert.notBlank("folder", folder); Assert.notBlank("name", name); return FileUtils - .readLineInClasspath(getPath(TEMPLATE_FOLDER, DEPENDENCIES_FOLDER, folderType, PACKAGE_JSON), DQ + name + DQ) + .readLineInClasspath(getPath(TEMPLATE_FOLDER, DEPENDENCIES_FOLDER, folder, PACKAGE_JSON), DQ + name + DQ) .map(readValue -> { String[] result = readValue.split(":"); if (result.length == 2) { diff --git a/src/main/java/tech/jhipster/lite/generator/packagemanager/npm/domain/NpmService.java b/src/main/java/tech/jhipster/lite/generator/packagemanager/npm/domain/NpmService.java index ba7c5deec2d..357638062a9 100644 --- a/src/main/java/tech/jhipster/lite/generator/packagemanager/npm/domain/NpmService.java +++ b/src/main/java/tech/jhipster/lite/generator/packagemanager/npm/domain/NpmService.java @@ -11,5 +11,6 @@ public interface NpmService { void install(Project project); void prettify(Project project); + Optional getVersion(String folder, String name); Optional getVersionInCommon(String name); } diff --git a/src/main/resources/generator/client/vite/vue3/.eslintrc.js b/src/main/resources/generator/client/vite/vue3/.eslintrc.js new file mode 100644 index 00000000000..2f67f9b4e86 --- /dev/null +++ b/src/main/resources/generator/client/vite/vue3/.eslintrc.js @@ -0,0 +1,13 @@ +module.exports = { + env: { + node: true, + }, + extends: ['eslint:recommended', 'plugin:vue/vue3-recommended', '@vue/eslint-config-typescript', 'prettier'], + parserOptions: { + parser: '@typescript-eslint/parser', + }, + rules: { + quotes: ['error', 'single', { avoidEscape: true }], + '@typescript-eslint/no-unused-vars': ['error'], + }, +}; diff --git a/src/main/resources/generator/client/vite/vue3/jest.config.js b/src/main/resources/generator/client/vite/vue3/jest.config.js new file mode 100644 index 00000000000..af1a85ab68e --- /dev/null +++ b/src/main/resources/generator/client/vite/vue3/jest.config.js @@ -0,0 +1,27 @@ +module.exports = { + moduleFileExtensions: ['js', 'ts', 'json', 'vue'], + transform: { + '^.+\\.ts$': 'ts-jest', + '^.+\\.vue$': 'vue-jest', + '.+\\.(css|styl|less|sass|scss|png|jpg|svg|ttf|woff|woff2)$': 'jest-transform-stub', + }, + collectCoverage: true, + collectCoverageFrom: [ + 'src/main/webapp/**/*.{js,ts,vue}', + '!src/main/webapp/**/*.component.ts', + '!src/main/webapp/app/main.ts', + '!**/*.d.ts', + ], + coverageReporters: ['html', 'json-summary', 'text-summary', 'lcov', 'clover'], + coverageDirectory: '/target/test-results/', + coverageThreshold: { + global: { + statements: 100, + branches: 100, + functions: 100, + lines: 100, + }, + }, + modulePathIgnorePatterns: ['/src/main/resources/'], + testResultsProcessor: 'jest-sonar-reporter', +}; diff --git a/src/main/resources/generator/client/vite/vue3/test/spec/common/primary/app/App.spec.ts.mustache b/src/main/resources/generator/client/vite/vue3/test/spec/common/primary/app/App.spec.ts.mustache new file mode 100644 index 00000000000..65ec6acf2f8 --- /dev/null +++ b/src/main/resources/generator/client/vite/vue3/test/spec/common/primary/app/App.spec.ts.mustache @@ -0,0 +1,16 @@ +import { shallowMount, VueWrapper } from '@vue/test-utils'; +import { AppVue } from '../../../../../../main/webapp/app/common/primary/app'; + +let wrapper: VueWrapper; + +const wrap = () => { + wrapper = shallowMount(AppVue); +}; + +describe('App', () => { + it('should exist', () => { + wrap(); + + expect(wrapper.exists()).toBe(true); + }); +}); diff --git a/src/main/resources/generator/client/vite/vue3/tsconfig.json b/src/main/resources/generator/client/vite/vue3/tsconfig.json new file mode 100644 index 00000000000..aa86762fadc --- /dev/null +++ b/src/main/resources/generator/client/vite/vue3/tsconfig.json @@ -0,0 +1,17 @@ +{ + "compilerOptions": { + "target": "esnext", + "useDefineForClassFields": true, + "module": "esnext", + "moduleResolution": "node", + "strict": true, + "jsx": "preserve", + "sourceMap": true, + "resolveJsonModule": true, + "esModuleInterop": true, + "lib": ["esnext", "dom"], + "types": ["vite/client", "@types/jest"] + }, + "include": ["src/main/webapp/**/*.ts", "src/main/webapp/**/*.d.ts", "src/main/webapp/**/*.tsx", "src/main/webapp/**/*.vue"], + "exclude": ["./node_modules"] +} diff --git a/src/main/resources/generator/client/vite/vue3/vite.config.ts b/src/main/resources/generator/client/vite/vue3/vite.config.ts new file mode 100644 index 00000000000..93878b7ef7f --- /dev/null +++ b/src/main/resources/generator/client/vite/vue3/vite.config.ts @@ -0,0 +1,19 @@ +import { defineConfig } from 'vite'; +import vue from '@vitejs/plugin-vue'; + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [ + vue({ + template: { + compilerOptions: { + isCustomElement: tag => /^x-/.test(tag), + }, + }, + }), + ], + build: { + outDir: '../../../target/classes/static', + }, + root: 'src/main/webapp', +}); diff --git a/src/main/resources/generator/client/vite/vue3/webapp/app/common/primary/app/App.component.ts.mustache b/src/main/resources/generator/client/vite/vue3/webapp/app/common/primary/app/App.component.ts.mustache new file mode 100644 index 00000000000..64bbd636024 --- /dev/null +++ b/src/main/resources/generator/client/vite/vue3/webapp/app/common/primary/app/App.component.ts.mustache @@ -0,0 +1,3 @@ +import { Vue } from 'vue-class-component'; + +export default class App extends Vue {} diff --git a/src/main/resources/generator/client/vite/vue3/webapp/app/common/primary/app/App.vue.mustache b/src/main/resources/generator/client/vite/vue3/webapp/app/common/primary/app/App.vue.mustache new file mode 100644 index 00000000000..0d25e0d4ee6 --- /dev/null +++ b/src/main/resources/generator/client/vite/vue3/webapp/app/common/primary/app/App.vue.mustache @@ -0,0 +1,97 @@ + + + + + diff --git a/src/main/resources/generator/client/vite/vue3/webapp/app/common/primary/app/index.ts.mustache b/src/main/resources/generator/client/vite/vue3/webapp/app/common/primary/app/index.ts.mustache new file mode 100644 index 00000000000..56c48ccc20e --- /dev/null +++ b/src/main/resources/generator/client/vite/vue3/webapp/app/common/primary/app/index.ts.mustache @@ -0,0 +1,4 @@ +import AppComponent from './App.component'; +import AppVue from './App.vue'; + +export { AppComponent, AppVue }; diff --git a/src/main/resources/generator/client/vite/vue3/webapp/app/env.d.ts.mustache b/src/main/resources/generator/client/vite/vue3/webapp/app/env.d.ts.mustache new file mode 100644 index 00000000000..a735ff23942 --- /dev/null +++ b/src/main/resources/generator/client/vite/vue3/webapp/app/env.d.ts.mustache @@ -0,0 +1,8 @@ +/// + +declare module '*.vue' { + import { DefineComponent } from 'vue'; + // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/ban-types + const component: DefineComponent<{}, {}, any>; + export default component; +} diff --git a/src/main/resources/generator/client/vite/vue3/webapp/app/main.ts.mustache b/src/main/resources/generator/client/vite/vue3/webapp/app/main.ts.mustache new file mode 100644 index 00000000000..e23d3f7af6e --- /dev/null +++ b/src/main/resources/generator/client/vite/vue3/webapp/app/main.ts.mustache @@ -0,0 +1,4 @@ +import { createApp } from 'vue'; +import App from './common/primary/app/App.vue'; + +createApp(App).mount('#app'); diff --git a/src/main/resources/generator/client/vite/vue3/webapp/content/images/JHipster-Lite-neon-green.png b/src/main/resources/generator/client/vite/vue3/webapp/content/images/JHipster-Lite-neon-green.png new file mode 100644 index 00000000000..a5f20afefe6 Binary files /dev/null and b/src/main/resources/generator/client/vite/vue3/webapp/content/images/JHipster-Lite-neon-green.png differ diff --git a/src/main/resources/generator/client/vite/vue3/webapp/content/images/logo.png b/src/main/resources/generator/client/vite/vue3/webapp/content/images/logo.png new file mode 100644 index 00000000000..f3d2503fc2a Binary files /dev/null and b/src/main/resources/generator/client/vite/vue3/webapp/content/images/logo.png differ diff --git a/src/main/resources/generator/client/vite/vue3/webapp/index.html.mustache b/src/main/resources/generator/client/vite/vue3/webapp/index.html.mustache new file mode 100644 index 00000000000..32719989826 --- /dev/null +++ b/src/main/resources/generator/client/vite/vue3/webapp/index.html.mustache @@ -0,0 +1,13 @@ + + + + + + + Vite App + + +
+ + + diff --git a/src/main/resources/generator/dependencies/vite/vue3/package.json b/src/main/resources/generator/dependencies/vite/vue3/package.json new file mode 100644 index 00000000000..06089d68afa --- /dev/null +++ b/src/main/resources/generator/dependencies/vite/vue3/package.json @@ -0,0 +1,29 @@ +{ + "name": "jhlite-dependencies", + "version": "0.0.0", + "description": "JHipster Lite : used for Vite+Vue3 dependencies", + "license": "Apache-2.0", + "dependencies": { + "vue": "3.2.25", + "vue-class-component": "^8.0.0-0" + }, + "devDependencies": { + "@rushstack/eslint-patch": "1.1.0", + "@types/jest": "27.4.0", + "@typescript-eslint/parser": "5.11.0", + "@vitejs/plugin-vue": "2.0.0", + "@vue/eslint-config-typescript": "10.0.0", + "@vue/test-utils": "2.0.0-rc.18", + "eslint": "8.8.0", + "eslint-config-prettier": "8.3.0", + "eslint-plugin-vue": "8.4.1", + "jest": "26.6.3", + "jest-sonar-reporter": "2.0.0", + "jest-transform-stub": "2.0.0", + "ts-jest": "26.5.6", + "typescript": "4.5.5", + "vite": "^2.7.2", + "vue-jest": "5.0.0-alpha.10", + "vue-tsc": "0.29.8" + } +} diff --git a/src/test/java/tech/jhipster/lite/generator/client/vite/vue/core/application/ViteVueApplicationServiceIT.java b/src/test/java/tech/jhipster/lite/generator/client/vite/vue/core/application/ViteVueApplicationServiceIT.java new file mode 100644 index 00000000000..a4643ec2bdf --- /dev/null +++ b/src/test/java/tech/jhipster/lite/generator/client/vite/vue/core/application/ViteVueApplicationServiceIT.java @@ -0,0 +1,32 @@ +package tech.jhipster.lite.generator.client.vite.vue.core.application; + +import static tech.jhipster.lite.TestUtils.tmpProjectWithPackageJson; +import static tech.jhipster.lite.generator.client.vite.vue.core.application.ViteVueAssert.*; + +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import tech.jhipster.lite.IntegrationTest; +import tech.jhipster.lite.generator.project.domain.Project; + +@IntegrationTest +class ViteVueApplicationServiceIT { + + @Autowired + ViteVueApplicationService viteVueApplicationService; + + @Test + void shouldAddViteVue() { + Project project = tmpProjectWithPackageJson(); + + viteVueApplicationService.addViteVue(project); + + assertDependency(project); + assertScripts(project); + + assertViteConfigFiles(project); + assertRootFiles(project); + assertAppFiles(project); + + assertJestSonar(project); + } +} diff --git a/src/test/java/tech/jhipster/lite/generator/client/vite/vue/core/application/ViteVueAssert.java b/src/test/java/tech/jhipster/lite/generator/client/vite/vue/core/application/ViteVueAssert.java new file mode 100644 index 00000000000..3148db02006 --- /dev/null +++ b/src/test/java/tech/jhipster/lite/generator/client/vite/vue/core/application/ViteVueAssert.java @@ -0,0 +1,55 @@ +package tech.jhipster.lite.generator.client.vite.vue.core.application; + +import static tech.jhipster.lite.TestUtils.assertFileContent; +import static tech.jhipster.lite.TestUtils.assertFileExist; +import static tech.jhipster.lite.common.domain.WordUtils.DQ; +import static tech.jhipster.lite.generator.project.domain.Constants.PACKAGE_JSON; + +import java.util.List; +import tech.jhipster.lite.generator.client.vite.vue.core.domain.ViteVue; +import tech.jhipster.lite.generator.project.domain.Project; + +public class ViteVueAssert { + + private ViteVueAssert() {} + + public static void assertDependency(Project project) { + ViteVue.dependencies().forEach(dependency -> assertFileContent(project, PACKAGE_JSON, DQ + dependency + DQ)); + ViteVue.devDependencies().forEach(devDependency -> assertFileContent(project, PACKAGE_JSON, DQ + devDependency + DQ)); + } + + public static void assertScripts(Project project) { + assertFileContent(project, PACKAGE_JSON, "\"build\": \"vue-tsc --noEmit && vite build --emptyOutDir\""); + assertFileContent(project, PACKAGE_JSON, "\"dev\": \"vite\""); + assertFileContent(project, PACKAGE_JSON, "\"preview\": \"vite preview\""); + assertFileContent(project, PACKAGE_JSON, "\"test\": \"jest src/test/javascript/spec\""); + } + + public static void assertViteConfigFiles(Project project) { + assertFileExist(project, ".eslintrc.js"); + assertFileExist(project, "jest.config.js"); + assertFileExist(project, "tsconfig.json"); + assertFileExist(project, "vite.config.ts"); + } + + public static void assertRootFiles(Project project) { + assertFileExist(project, "src/main/webapp/index.html"); + assertFileExist(project, "src/main/webapp/app/env.d.ts"); + assertFileExist(project, "src/main/webapp/app/main.ts"); + } + + public static void assertAppFiles(Project project) { + assertFileExist(project, "src/main/webapp/app/common/primary/app/App.component.ts"); + assertFileExist(project, "src/main/webapp/app/common/primary/app/App.vue"); + assertFileExist(project, "src/main/webapp/app/common/primary/app/index.ts"); + assertFileExist(project, "src/test/javascript/spec/common/primary/app/App.spec.ts"); + } + + public static void assertJestSonar(Project project) { + assertFileContent( + project, + PACKAGE_JSON, + List.of("\"jestSonar\": {", "\"reportPath\": \"target/test-results/jest\",", "\"reportFile\": \"TESTS-results-sonar.xml\"", "}") + ); + } +} diff --git a/src/test/java/tech/jhipster/lite/generator/client/vite/vue/core/domain/ViteVueDomainServiceTest.java b/src/test/java/tech/jhipster/lite/generator/client/vite/vue/core/domain/ViteVueDomainServiceTest.java new file mode 100644 index 00000000000..0fcfa64585d --- /dev/null +++ b/src/test/java/tech/jhipster/lite/generator/client/vite/vue/core/domain/ViteVueDomainServiceTest.java @@ -0,0 +1,113 @@ +package tech.jhipster.lite.generator.client.vite.vue.core.domain; + +import static org.assertj.core.api.Assertions.*; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.*; +import static tech.jhipster.lite.TestUtils.tmpProject; +import static tech.jhipster.lite.TestUtils.tmpProjectWithPackageJson; + +import java.util.Optional; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import tech.jhipster.lite.UnitTest; +import tech.jhipster.lite.error.domain.GeneratorException; +import tech.jhipster.lite.generator.packagemanager.npm.domain.NpmService; +import tech.jhipster.lite.generator.project.domain.Project; +import tech.jhipster.lite.generator.project.domain.ProjectRepository; + +@UnitTest +@ExtendWith(MockitoExtension.class) +class ViteVueDomainServiceTest { + + @Mock + ProjectRepository projectRepository; + + @Mock + NpmService npmService; + + @InjectMocks + private ViteVueDomainService viteVueDomainService; + + @Test + void shouldAddViteVue() { + Project project = tmpProjectWithPackageJson(); + when(npmService.getVersion(anyString(), anyString())).thenReturn(Optional.of("0.0.0")); + + assertThatCode(() -> viteVueDomainService.addViteVue(project)).doesNotThrowAnyException(); + } + + @Test + void shouldAddDependencies() { + Project project = tmpProjectWithPackageJson(); + when(npmService.getVersion(anyString(), anyString())).thenReturn(Optional.of("0.0.0")); + + viteVueDomainService.addDependencies(project); + + verify(npmService, times(2)).addDependency(any(Project.class), anyString(), anyString()); + } + + @Test + void shouldNotAddDependencies() { + Project project = tmpProjectWithPackageJson(); + + assertThatThrownBy(() -> viteVueDomainService.addDependencies(project)).isExactlyInstanceOf(GeneratorException.class); + } + + @Test + void shouldAddDevDependencies() { + Project project = tmpProjectWithPackageJson(); + when(npmService.getVersion(anyString(), anyString())).thenReturn(Optional.of("0.0.0")); + + viteVueDomainService.addDevDependencies(project); + + verify(npmService, times(17)).addDevDependency(any(Project.class), anyString(), anyString()); + } + + @Test + void shouldNotAddDevDependencies() { + Project project = tmpProjectWithPackageJson(); + + assertThatThrownBy(() -> viteVueDomainService.addDevDependencies(project)).isExactlyInstanceOf(GeneratorException.class); + } + + @Test + void shouldAddScripts() { + Project project = tmpProjectWithPackageJson(); + + viteVueDomainService.addScripts(project); + + verify(npmService, times(4)).addScript(any(Project.class), anyString(), anyString()); + } + + @Test + void shouldAddViteConfigFiles() { + Project project = tmpProjectWithPackageJson(); + + viteVueDomainService.addViteConfigFiles(project); + + verify(projectRepository, times(4)).add(any(Project.class), anyString(), anyString()); + } + + @Test + void shouldAddRootFiles() { + Project project = tmpProject(); + + viteVueDomainService.addRootFiles(project); + + verify(projectRepository, times(3)).template(any(Project.class), anyString(), anyString(), anyString()); + verify(projectRepository, times(2)).add(any(Project.class), anyString(), anyString(), anyString()); + } + + @Test + void shouldAddAppFiles() { + Project project = tmpProject(); + + viteVueDomainService.addAppFiles(project); + + verify(projectRepository, times(4)).template(any(Project.class), anyString(), anyString(), anyString()); + } +} diff --git a/src/test/java/tech/jhipster/lite/generator/client/vite/vue/core/infrastructure/config/ViteVueBeanConfigurationIT.java b/src/test/java/tech/jhipster/lite/generator/client/vite/vue/core/infrastructure/config/ViteVueBeanConfigurationIT.java new file mode 100644 index 00000000000..f4b8ef41a29 --- /dev/null +++ b/src/test/java/tech/jhipster/lite/generator/client/vite/vue/core/infrastructure/config/ViteVueBeanConfigurationIT.java @@ -0,0 +1,21 @@ +package tech.jhipster.lite.generator.client.vite.vue.core.infrastructure.config; + +import static org.assertj.core.api.Assertions.*; + +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationContext; +import tech.jhipster.lite.IntegrationTest; +import tech.jhipster.lite.generator.client.vite.vue.core.domain.ViteVueDomainService; + +@IntegrationTest +class ViteVueBeanConfigurationIT { + + @Autowired + ApplicationContext applicationContext; + + @Test + void shouldGetBean() { + assertThat(applicationContext.getBean("viteVueService")).isNotNull().isInstanceOf(ViteVueDomainService.class); + } +} diff --git a/src/test/java/tech/jhipster/lite/generator/client/vite/vue/core/infrastructure/primary/rest/ViveVueResourceIT.java b/src/test/java/tech/jhipster/lite/generator/client/vite/vue/core/infrastructure/primary/rest/ViveVueResourceIT.java new file mode 100644 index 00000000000..7bbe1f3d132 --- /dev/null +++ b/src/test/java/tech/jhipster/lite/generator/client/vite/vue/core/infrastructure/primary/rest/ViveVueResourceIT.java @@ -0,0 +1,47 @@ +package tech.jhipster.lite.generator.client.vite.vue.core.infrastructure.primary.rest; + +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; +import static tech.jhipster.lite.TestUtils.readFileToObject; +import static tech.jhipster.lite.common.domain.FileUtils.tmpDirForTest; +import static tech.jhipster.lite.generator.client.vite.vue.core.application.ViteVueAssert.*; + +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.http.MediaType; +import org.springframework.test.web.servlet.MockMvc; +import tech.jhipster.lite.IntegrationTest; +import tech.jhipster.lite.TestUtils; +import tech.jhipster.lite.generator.init.application.InitApplicationService; +import tech.jhipster.lite.generator.project.domain.Project; +import tech.jhipster.lite.generator.project.infrastructure.primary.dto.ProjectDTO; + +@IntegrationTest +@AutoConfigureMockMvc +class ViveVueResourceIT { + + @Autowired + MockMvc mockMvc; + + @Autowired + InitApplicationService initApplicationService; + + @Test + void shouldAddViteVue() throws Exception { + ProjectDTO projectDTO = readFileToObject("json/chips.json", ProjectDTO.class).folder(tmpDirForTest()); + Project project = ProjectDTO.toProject(projectDTO); + initApplicationService.init(project); + + mockMvc + .perform(post("/api/vite/vue").contentType(MediaType.APPLICATION_JSON).content(TestUtils.convertObjectToJsonBytes(projectDTO))) + .andExpect(status().isOk()); + + assertDependency(project); + assertScripts(project); + + assertViteConfigFiles(project); + assertRootFiles(project); + assertAppFiles(project); + } +} diff --git a/src/test/java/tech/jhipster/lite/generator/packagemanager/npm/domain/NpmDomainServiceTest.java b/src/test/java/tech/jhipster/lite/generator/packagemanager/npm/domain/NpmDomainServiceTest.java index 6e3695d49f5..fd12971ca05 100644 --- a/src/test/java/tech/jhipster/lite/generator/packagemanager/npm/domain/NpmDomainServiceTest.java +++ b/src/test/java/tech/jhipster/lite/generator/packagemanager/npm/domain/NpmDomainServiceTest.java @@ -79,36 +79,36 @@ void shouldPrettify() { class GetVersionInCommonTest { @Test - void shouldGetVersion() { + void shouldGetVersionInCommon() { assertThat(npmDomainService.getVersionInCommon("prettier-plugin-java")).isNotEmpty(); } @Test - void shouldNotGetVersionForNull() { + void shouldNotGetVersionInCommonForNull() { assertThatThrownBy(() -> npmDomainService.getVersionInCommon(null)) .isExactlyInstanceOf(MissingMandatoryValueException.class) .hasMessageContaining("name"); } @Test - void shouldNotGetVersionForBlank() { + void shouldNotGetVersionInCommonForBlank() { assertThatThrownBy(() -> npmDomainService.getVersionInCommon(" ")) .isExactlyInstanceOf(MissingMandatoryValueException.class) .hasMessageContaining("name"); } @Test - void shouldNotGetVersion() { + void shouldNotGetVersionInCommon() { assertThat(npmDomainService.getVersionInCommon("unknown")).isEmpty(); } @Test - void shouldNotGetVersionForDescription() { + void shouldNotGetVersionInCommonForDescription() { assertThat(npmDomainService.getVersionInCommon("description")).isEmpty(); } @Test - void shouldNotGetVersionForCloseBracket() { + void shouldNotGetVersionInCommonForCloseBracket() { assertThat(npmDomainService.getVersionInCommon("}")).isEmpty(); } } diff --git a/tests-ci/generate.sh b/tests-ci/generate.sh index 553b801b1f9..6d34c44b929 100755 --- a/tests-ci/generate.sh +++ b/tests-ci/generate.sh @@ -48,6 +48,9 @@ if [[ $filename == 'full-default' ]]; then callApi "/api/servers/spring-boot/cache/ehcache/java-configuration" + callApi "/api/frontend-maven-plugin" + callApi "/api/vite/vue" + elif [[ $filename == 'tomcat-mysql-ehcachexml' ]]; then callApi "/api/projects/init" callApi "/api/build-tools/maven"