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:
parent
4eea819b24
commit
0d1a5e0ffc
12 changed files with 5151 additions and 35 deletions
|
@ -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 a new issue