mirror of
				https://github.com/go-gitea/gitea.git
				synced 2025-10-31 21:28:11 +09:00 
			
		
		
		
	Add frontend testing, require node 12 (#15315)
- Add basic frontend unit testing infrastructure using jest in ESM mode - Rename 'make test' to 'make test-backend' - Introduce 'make test-frontend' and 'make test' that runs both - Bump Node.js requirement to v12. v10 will be EOL in less than a month. - Convert all build-related JS files to ESM. I opted to run frontend tests run as part of the compliance pipeline because they complete fast and are not platform-specific like the golang tests.
This commit is contained in:
		| @@ -70,11 +70,17 @@ steps: | |||||||
|       - make checks-backend |       - make checks-backend | ||||||
|     depends_on: [lint-backend] |     depends_on: [lint-backend] | ||||||
|  |  | ||||||
|  |   - name: test-frontend | ||||||
|  |     image: node:14 | ||||||
|  |     commands: | ||||||
|  |       - make test-frontend | ||||||
|  |     depends_on: [lint-frontend] | ||||||
|  |  | ||||||
|   - name: build-frontend |   - name: build-frontend | ||||||
|     image: node:14 |     image: node:14 | ||||||
|     commands: |     commands: | ||||||
|       - make frontend |       - make frontend | ||||||
|     depends_on: [lint-frontend] |     depends_on: [test-frontend] | ||||||
|  |  | ||||||
|   - name: build-backend-no-gcc |   - name: build-backend-no-gcc | ||||||
|     pull: always |     pull: always | ||||||
|   | |||||||
| @@ -52,6 +52,12 @@ overrides: | |||||||
|     rules: |     rules: | ||||||
|       import/no-unresolved: [0] |       import/no-unresolved: [0] | ||||||
|       import/no-extraneous-dependencies: [0] |       import/no-extraneous-dependencies: [0] | ||||||
|  |   - files: ["*.test.js"] | ||||||
|  |     env: | ||||||
|  |       jest: true | ||||||
|  |   - files: ["*.config.js"] | ||||||
|  |     rules: | ||||||
|  |       import/no-unused-modules: [0] | ||||||
|  |  | ||||||
| rules: | rules: | ||||||
|   accessor-pairs: [2] |   accessor-pairs: [2] | ||||||
|   | |||||||
							
								
								
									
										18
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										18
									
								
								Makefile
									
									
									
									
									
								
							| @@ -28,7 +28,7 @@ COMMA := , | |||||||
|  |  | ||||||
| XGO_VERSION := go-1.16.x | XGO_VERSION := go-1.16.x | ||||||
| MIN_GO_VERSION := 001014000 | MIN_GO_VERSION := 001014000 | ||||||
| MIN_NODE_VERSION := 010013000 | MIN_NODE_VERSION := 012017000 | ||||||
|  |  | ||||||
| DOCKER_IMAGE ?= gitea/gitea | DOCKER_IMAGE ?= gitea/gitea | ||||||
| DOCKER_TAG ?= latest | DOCKER_TAG ?= latest | ||||||
| @@ -173,6 +173,9 @@ help: | |||||||
| 	@echo " - checks                           run various consistency checks" | 	@echo " - checks                           run various consistency checks" | ||||||
| 	@echo " - checks-frontend                  check frontend files" | 	@echo " - checks-frontend                  check frontend files" | ||||||
| 	@echo " - checks-backend                   check backend files" | 	@echo " - checks-backend                   check backend files" | ||||||
|  | 	@echo " - test                             test everything" | ||||||
|  | 	@echo " - test-frontend                    test frontend files" | ||||||
|  | 	@echo " - test-backend                     test backend files" | ||||||
| 	@echo " - webpack                          build webpack files" | 	@echo " - webpack                          build webpack files" | ||||||
| 	@echo " - svg                              build svg files" | 	@echo " - svg                              build svg files" | ||||||
| 	@echo " - fomantic                         build fomantic files" | 	@echo " - fomantic                         build fomantic files" | ||||||
| @@ -322,7 +325,7 @@ lint: lint-frontend lint-backend | |||||||
|  |  | ||||||
| .PHONY: lint-frontend | .PHONY: lint-frontend | ||||||
| lint-frontend: node_modules | lint-frontend: node_modules | ||||||
| 	npx eslint --color --max-warnings=0 web_src/js build templates webpack.config.js | 	npx eslint --color --max-warnings=0 web_src/js build templates *.config.js | ||||||
| 	npx stylelint --color --max-warnings=0 web_src/less | 	npx stylelint --color --max-warnings=0 web_src/less | ||||||
|  |  | ||||||
| .PHONY: lint-backend | .PHONY: lint-backend | ||||||
| @@ -345,16 +348,23 @@ watch-backend: go-check | |||||||
| 	air -c .air.conf | 	air -c .air.conf | ||||||
|  |  | ||||||
| .PHONY: test | .PHONY: test | ||||||
| test: | test: test-frontend test-backend | ||||||
|  |  | ||||||
|  | .PHONY: test-backend | ||||||
|  | test-backend: | ||||||
| 	@echo "Running go test with -tags '$(TEST_TAGS)'..." | 	@echo "Running go test with -tags '$(TEST_TAGS)'..." | ||||||
| 	@$(GO) test $(GOTESTFLAGS) -mod=vendor -tags='$(TEST_TAGS)' $(GO_PACKAGES) | 	@$(GO) test $(GOTESTFLAGS) -mod=vendor -tags='$(TEST_TAGS)' $(GO_PACKAGES) | ||||||
|  |  | ||||||
|  | .PHONY: test-frontend | ||||||
|  | test-frontend: | ||||||
|  | 	@NODE_OPTIONS="--experimental-vm-modules --no-warnings" npx jest --color | ||||||
|  |  | ||||||
| .PHONY: test-check | .PHONY: test-check | ||||||
| test-check: | test-check: | ||||||
| 	@echo "Running test-check..."; | 	@echo "Running test-check..."; | ||||||
| 	@diff=$$(git status -s); \ | 	@diff=$$(git status -s); \ | ||||||
| 	if [ -n "$$diff" ]; then \ | 	if [ -n "$$diff" ]; then \ | ||||||
| 		echo "make test has changed files in the source tree:"; \ | 		echo "make test-backend has changed files in the source tree:"; \ | ||||||
| 		echo "$${diff}"; \ | 		echo "$${diff}"; \ | ||||||
| 		echo "You should change the tests to create these files in a temporary directory."; \ | 		echo "You should change the tests to create these files in a temporary directory."; \ | ||||||
| 		echo "Do not simply add these files to .gitignore"; \ | 		echo "Do not simply add these files to .gitignore"; \ | ||||||
|   | |||||||
| @@ -77,7 +77,7 @@ or if sqlite support is required: | |||||||
| The `build` target is split into two sub-targets: | The `build` target is split into two sub-targets: | ||||||
|  |  | ||||||
| - `make backend` which requires [Go 1.13](https://golang.org/dl/) or greater. | - `make backend` which requires [Go 1.13](https://golang.org/dl/) or greater. | ||||||
| - `make frontend` which requires [Node.js 10.13](https://nodejs.org/en/download/) or greater. | - `make frontend` which requires [Node.js 12.17](https://nodejs.org/en/download/) or greater. | ||||||
|  |  | ||||||
| If pre-built frontend files are present it is possible to only build the backend: | If pre-built frontend files are present it is possible to only build the backend: | ||||||
|  |  | ||||||
|   | |||||||
| @@ -1,12 +1,11 @@ | |||||||
| #!/usr/bin/env node | import imageminZopfli from 'imagemin-zopfli'; | ||||||
| 'use strict'; | import {optimize, extendDefaultPlugins} from 'svgo'; | ||||||
|  | import {fabric} from 'fabric'; | ||||||
| const imageminZopfli = require('imagemin-zopfli'); | import {readFile, writeFile} from 'fs/promises'; | ||||||
| const {optimize, extendDefaultPlugins} = require('svgo'); | import {resolve, dirname} from 'path'; | ||||||
| const {fabric} = require('fabric'); | import {fileURLToPath} from 'url'; | ||||||
| const {readFile, writeFile} = require('fs').promises; |  | ||||||
| const {resolve} = require('path'); |  | ||||||
|  |  | ||||||
|  | const __dirname = dirname(fileURLToPath(import.meta.url)); | ||||||
| const logoFile = resolve(__dirname, '../assets/logo.svg'); | const logoFile = resolve(__dirname, '../assets/logo.svg'); | ||||||
|  |  | ||||||
| function exit(err) { | function exit(err) { | ||||||
|   | |||||||
| @@ -1,11 +1,10 @@ | |||||||
| #!/usr/bin/env node | import fastGlob from 'fast-glob'; | ||||||
| 'use strict'; | import {optimize, extendDefaultPlugins} from 'svgo'; | ||||||
|  | import {resolve, parse, dirname} from 'path'; | ||||||
| const fastGlob = require('fast-glob'); | import {readFile, writeFile, mkdir} from 'fs/promises'; | ||||||
| const {optimize, extendDefaultPlugins} = require('svgo'); | import {fileURLToPath} from 'url'; | ||||||
| const {resolve, parse} = require('path'); |  | ||||||
| const {readFile, writeFile, mkdir} = require('fs').promises; |  | ||||||
|  |  | ||||||
|  | const __dirname = dirname(fileURLToPath(import.meta.url)); | ||||||
| const glob = (pattern) => fastGlob.sync(pattern, {cwd: resolve(__dirname), absolute: true}); | const glob = (pattern) => fastGlob.sync(pattern, {cwd: resolve(__dirname), absolute: true}); | ||||||
| const outputDir = resolve(__dirname, '../public/img/svg'); | const outputDir = resolve(__dirname, '../public/img/svg'); | ||||||
|  |  | ||||||
|   | |||||||
| @@ -21,7 +21,7 @@ params: | |||||||
|   version: 1.13.7 |   version: 1.13.7 | ||||||
|   minGoVersion: 1.14 |   minGoVersion: 1.14 | ||||||
|   goVersion: 1.16 |   goVersion: 1.16 | ||||||
|   minNodeVersion: 10.13 |   minNodeVersion: 12.17 | ||||||
|  |  | ||||||
| outputs: | outputs: | ||||||
|   home: |   home: | ||||||
|   | |||||||
							
								
								
									
										10
									
								
								jest.config.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								jest.config.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,10 @@ | |||||||
|  | export default { | ||||||
|  |   setupFilesAfterEnv: ['jest-extended'], | ||||||
|  |   testTimeout: 20000, | ||||||
|  |   testMatch: [ | ||||||
|  |     '**/web_src/**/*.test.js', | ||||||
|  |   ], | ||||||
|  |   transform: {}, | ||||||
|  |   verbose: false, | ||||||
|  | }; | ||||||
|  |  | ||||||
							
								
								
									
										5051
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										5051
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -1,8 +1,9 @@ | |||||||
| { | { | ||||||
|   "license": "MIT", |   "license": "MIT", | ||||||
|   "private": true, |   "private": true, | ||||||
|  |   "type": "module", | ||||||
|   "engines": { |   "engines": { | ||||||
|     "node": ">= 10.13.0" |     "node": ">= 12.17.0" | ||||||
|   }, |   }, | ||||||
|   "dependencies": { |   "dependencies": { | ||||||
|     "@claviska/jquery-minicolors": "2.3.5", |     "@claviska/jquery-minicolors": "2.3.5", | ||||||
| @@ -50,6 +51,8 @@ | |||||||
|     "eslint-plugin-import": "2.22.1", |     "eslint-plugin-import": "2.22.1", | ||||||
|     "eslint-plugin-unicorn": "29.0.0", |     "eslint-plugin-unicorn": "29.0.0", | ||||||
|     "eslint-plugin-vue": "7.8.0", |     "eslint-plugin-vue": "7.8.0", | ||||||
|  |     "jest": "26.6.3", | ||||||
|  |     "jest-extended": "0.11.5", | ||||||
|     "stylelint": "13.12.0", |     "stylelint": "13.12.0", | ||||||
|     "stylelint-config-standard": "21.0.0", |     "stylelint-config-standard": "21.0.0", | ||||||
|     "svgo": "2.3.0", |     "svgo": "2.3.0", | ||||||
|   | |||||||
							
								
								
									
										29
									
								
								web_src/js/utils.test.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								web_src/js/utils.test.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,29 @@ | |||||||
|  | import { | ||||||
|  |   basename, extname, isObject, uniq, stripTags, | ||||||
|  | } from './utils.js'; | ||||||
|  |  | ||||||
|  | test('basename', () => { | ||||||
|  |   expect(basename('/path/to/file.js')).toEqual('file.js'); | ||||||
|  |   expect(basename('/path/to/file')).toEqual('file'); | ||||||
|  |   expect(basename('file.js')).toEqual('file.js'); | ||||||
|  | }); | ||||||
|  |  | ||||||
|  | test('extname', () => { | ||||||
|  |   expect(extname('/path/to/file.js')).toEqual('.js'); | ||||||
|  |   expect(extname('/path/')).toEqual(''); | ||||||
|  |   expect(extname('/path')).toEqual(''); | ||||||
|  |   expect(extname('file.js')).toEqual('.js'); | ||||||
|  | }); | ||||||
|  |  | ||||||
|  | test('isObject', () => { | ||||||
|  |   expect(isObject({})).toBeTrue(); | ||||||
|  |   expect(isObject([])).toBeFalse(); | ||||||
|  | }); | ||||||
|  |  | ||||||
|  | test('uniq', () => { | ||||||
|  |   expect(uniq([1, 1, 1, 2])).toEqual([1, 2]); | ||||||
|  | }); | ||||||
|  |  | ||||||
|  | test('stripTags', () => { | ||||||
|  |   expect(stripTags('<a>test</a>')).toEqual('test'); | ||||||
|  | }); | ||||||
| @@ -1,15 +1,18 @@ | |||||||
| const fastGlob = require('fast-glob'); | import fastGlob from 'fast-glob'; | ||||||
| const wrapAnsi = require('wrap-ansi'); | import wrapAnsi from 'wrap-ansi'; | ||||||
| const AddAssetPlugin = require('add-asset-webpack-plugin'); | import AddAssetPlugin from 'add-asset-webpack-plugin'; | ||||||
| const CssMinimizerPlugin = require('css-minimizer-webpack-plugin'); | import CssMinimizerPlugin from 'css-minimizer-webpack-plugin'; | ||||||
| const LicenseCheckerWebpackPlugin = require('license-checker-webpack-plugin'); | import LicenseCheckerWebpackPlugin from 'license-checker-webpack-plugin'; | ||||||
| const MiniCssExtractPlugin = require('mini-css-extract-plugin'); | import MiniCssExtractPlugin from 'mini-css-extract-plugin'; | ||||||
| const MonacoWebpackPlugin = require('monaco-editor-webpack-plugin'); | import MonacoWebpackPlugin from 'monaco-editor-webpack-plugin'; | ||||||
| const VueLoaderPlugin = require('vue-loader/lib/plugin'); | import {VueLoaderPlugin} from 'vue-loader'; | ||||||
| const {ESBuildMinifyPlugin} = require('esbuild-loader'); | import {ESBuildMinifyPlugin} from 'esbuild-loader'; | ||||||
| const {resolve, parse} = require('path'); | import {resolve, parse, dirname} from 'path'; | ||||||
| const {SourceMapDevToolPlugin} = require('webpack'); | import webpack from 'webpack'; | ||||||
|  | import {fileURLToPath} from 'url'; | ||||||
|  |  | ||||||
|  | const __dirname = dirname(fileURLToPath(import.meta.url)); | ||||||
|  | const {SourceMapDevToolPlugin} = webpack; | ||||||
| const glob = (pattern) => fastGlob.sync(pattern, {cwd: __dirname, absolute: true}); | const glob = (pattern) => fastGlob.sync(pattern, {cwd: __dirname, absolute: true}); | ||||||
|  |  | ||||||
| const themes = {}; | const themes = {}; | ||||||
| @@ -35,7 +38,7 @@ const filterCssImport = (url, ...args) => { | |||||||
|   return true; |   return true; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| module.exports = { | export default { | ||||||
|   mode: isProduction ? 'production' : 'development', |   mode: isProduction ? 'production' : 'development', | ||||||
|   entry: { |   entry: { | ||||||
|     index: [ |     index: [ | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user