Browse Source

Merge branch 'main' into feature/cgroup

Jaap Marcus 2 years ago
parent
commit
cee0d1f9c0

+ 3 - 1
.eslintignore

@@ -5,5 +5,7 @@
 **/node_modules/
 **/node_modules/
 **/vendor/
 **/vendor/
 
 
-# vitepress
+# VitePress
 **/.vitepress/dist/
 **/.vitepress/dist/
+!docs/.vitepress/
+docs/.vitepress/cache/

+ 26 - 0
.github/workflows/test.yml

@@ -0,0 +1,26 @@
+name: Test
+
+on:
+  pull_request:
+  push:
+    branches:
+      - main
+
+jobs:
+  docs:
+    name: Docs site
+    runs-on: ubuntu-latest
+    steps:
+      - name: Checkout code
+        uses: actions/checkout@v4
+
+      - name: Setup Node
+        uses: actions/setup-node@v4
+        with:
+          node-version: "lts/*"
+
+      - name: Install Node packages
+        run: npm ci --ignore-scripts
+
+      - name: Run docs site tests
+        run: npm run docs:test

+ 1 - 0
bin/v-run-cli-cmd

@@ -70,6 +70,7 @@ if [ "$basecmd" != 'ps' -a \
 	"$basecmd" != 'php8.0' -a \
 	"$basecmd" != 'php8.0' -a \
 	"$basecmd" != 'php8.1' -a \
 	"$basecmd" != 'php8.1' -a \
 	"$basecmd" != 'php8.2' -a \
 	"$basecmd" != 'php8.2' -a \
+	"$basecmd" != 'php8.3' -a \
 	"$basecmd" != 'php' -a \
 	"$basecmd" != 'php' -a \
 	"$basecmd" != "wp" -a \
 	"$basecmd" != "wp" -a \
 	"$basecmd" != 'composer' ]; then
 	"$basecmd" != 'composer' ]; then

+ 46 - 0
docs/.vitepress/theme/components/CopyToClipboardInput.test.js

@@ -0,0 +1,46 @@
+import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
+import { render, fireEvent, screen, cleanup, waitFor } from '@testing-library/vue';
+import CopyToClipboardInput from './CopyToClipboardInput.vue';
+
+// Mock the clipboard API
+Object.assign(navigator, {
+	clipboard: {
+		writeText: vi.fn(() => Promise.resolve()),
+	},
+});
+
+describe('CopyToClipboardInput', () => {
+	beforeEach(() => {
+		render(CopyToClipboardInput, {
+			props: { value: 'Test text' },
+		});
+	});
+
+	afterEach(() => {
+		cleanup();
+	});
+
+	it('renders correctly', () => {
+		const input = screen.getByRole('textbox');
+		const button = screen.getByRole('button', { name: 'Copy' });
+
+		expect(input).toBeTruthy();
+		expect(button).toBeTruthy();
+	});
+
+	it('selects text when input is focused', async () => {
+		const input = screen.getByRole('textbox');
+		await fireEvent.focus(input);
+
+		expect(input.selectionStart).toBe(0);
+		expect(input.selectionEnd).toBe('Test text'.length);
+	});
+
+	it('copies text to clipboard when button is clicked', async () => {
+		const button = screen.getByRole('button', { name: 'Copy' });
+		await fireEvent.click(button);
+
+		expect(navigator.clipboard.writeText).toHaveBeenCalledWith('Test text');
+		await waitFor(() => expect(button.textContent).toBe('Copied!'));
+	});
+});

+ 83 - 0
docs/.vitepress/theme/components/InstallBuilder.test.js

@@ -0,0 +1,83 @@
+import { describe, it, expect, beforeEach, afterEach } from 'vitest';
+import { render, fireEvent, screen, cleanup, waitFor } from '@testing-library/vue';
+import FloatingVue from 'floating-vue';
+import InstallBuilder from './InstallBuilder.vue';
+
+describe('InstallBuilder', () => {
+	const options = [
+		{ flag: 'option1', label: 'Option 1', description: 'Description for Option 1', default: 'no' },
+		{
+			flag: 'option2',
+			label: 'Option 2',
+			description: 'Description for Option 2',
+			type: 'text',
+			default: '',
+		},
+		{
+			flag: 'option3',
+			label: 'Option 3',
+			description: 'Description for Option 3',
+			type: 'select',
+			options: [
+				{ value: 'val1', label: 'Value 1' },
+				{ value: 'val2', label: 'Value 2' },
+			],
+			default: 'val1',
+		},
+	];
+
+	beforeEach(() => {
+		render(InstallBuilder, {
+			props: { options },
+			global: {
+				plugins: [FloatingVue],
+			},
+		});
+	});
+
+	afterEach(() => {
+		cleanup();
+	});
+
+	it('renders all options correctly', () => {
+		options.forEach((option) => {
+			expect(screen.getByLabelText(option.label)).toBeTruthy();
+		});
+	});
+
+	it('toggles an option when clicked', async () => {
+		const option1 = screen.getByLabelText(options[0].label);
+		await fireEvent.click(option1);
+		expect(option1.checked).toBe(true);
+	});
+
+	it('updates the installation command when an option is toggled', async () => {
+		const option1 = screen.getByLabelText(options[0].label);
+		await fireEvent.click(option1);
+		waitFor(() =>
+			expect(screen.getByDisplayValue(/bash hst-install.sh --option1 yes/)).toBeTruthy(),
+		);
+	});
+
+	it('updates the installation command when option text input changes', async () => {
+		const option2 = screen.getByLabelText(options[1].label);
+		await fireEvent.click(option2);
+
+		const textInput = screen.getByLabelText(options[1].description);
+		await fireEvent.update(textInput, 'custom-value');
+
+		expect(screen.getByDisplayValue(/bash hst-install.sh --option2 custom-value/)).toBeTruthy();
+	});
+
+	it('updates the installation command when option select input changes', async () => {
+		const option3 = screen.getByLabelText(options[2].label);
+		await fireEvent.click(option3);
+
+		const selectInput = screen.getByLabelText(options[2].description);
+		await fireEvent.update(selectInput, { target: { value: 'val2' } });
+
+		waitFor(() =>
+			expect(screen.getByDisplayValue(/bash hst-install.sh --option3 val2/)).toBeTruthy(),
+		);
+	});
+});

+ 1 - 1
docs/.vitepress/theme/index.js

@@ -4,9 +4,9 @@ import '@fortawesome/fontawesome-free/css/solid.css';
 import './styles/base.css';
 import './styles/base.css';
 import './styles/vars.css';
 import './styles/vars.css';
 import 'floating-vue/dist/style.css';
 import 'floating-vue/dist/style.css';
+import FloatingVue from 'floating-vue';
 import FeaturePage from './components/FeaturePage.vue';
 import FeaturePage from './components/FeaturePage.vue';
 import InstallPage from './components/InstallPage.vue';
 import InstallPage from './components/InstallPage.vue';
-import FloatingVue from 'floating-vue';
 
 
 export default {
 export default {
 	...Theme,
 	...Theme,

+ 9 - 0
docs/.vitepress/vitest.config.js

@@ -0,0 +1,9 @@
+import { defineConfig } from 'vitest/config';
+import vue from '@vitejs/plugin-vue';
+
+export default defineConfig({
+	test: {
+		environment: 'jsdom',
+	},
+	plugins: [vue()],
+});

+ 2 - 2
func/db.sh

@@ -74,7 +74,7 @@ mysql_connect() {
 		if [ "$notify" != 'no' ]; then
 		if [ "$notify" != 'no' ]; then
 			email=$(grep CONTACT "$HESTIA/data/users/$ROOT_USER/user.conf" | cut -f 2 -d \')
 			email=$(grep CONTACT "$HESTIA/data/users/$ROOT_USER/user.conf" | cut -f 2 -d \')
 			subj="MySQL connection error on $(hostname)"
 			subj="MySQL connection error on $(hostname)"
-			echo -e "Can't connect to MySQL $HOST\n$(cat $mysql_out)" \
+			echo -e "Can't connect to MySQL $HOST:$PORT\n$(cat $mysql_out)" \
 				| $SENDMAIL -s "$subj" $email
 				| $SENDMAIL -s "$subj" $email
 		fi
 		fi
 		rm -f $mysql_out
 		rm -f $mysql_out
@@ -147,7 +147,7 @@ psql_connect() {
 		if [ "$notify" != 'no' ]; then
 		if [ "$notify" != 'no' ]; then
 			email=$(grep CONTACT "$HESTIA/data/users/$ROOT_USER/user.conf" | cut -f 2 -d \')
 			email=$(grep CONTACT "$HESTIA/data/users/$ROOT_USER/user.conf" | cut -f 2 -d \')
 			subj="PostgreSQL connection error on $(hostname)"
 			subj="PostgreSQL connection error on $(hostname)"
-			echo -e "Can't connect to PostgreSQL $HOST\n$(cat /tmp/e.psql)" \
+			echo -e "Can't connect to PostgreSQL $HOST:$PORT\n$(cat /tmp/e.psql)" \
 				| $SENDMAIL -s "$subj" $email
 				| $SENDMAIL -s "$subj" $email
 		fi
 		fi
 		echo "Error: Connection to $HOST failed"
 		echo "Error: Connection to $HOST failed"

File diff suppressed because it is too large
+ 643 - 77
package-lock.json


+ 10 - 5
package.json

@@ -10,6 +10,7 @@
 		"docs:dev": "vitepress dev docs",
 		"docs:dev": "vitepress dev docs",
 		"docs:build": "vitepress build docs",
 		"docs:build": "vitepress build docs",
 		"docs:serve": "vitepress serve docs",
 		"docs:serve": "vitepress serve docs",
+		"docs:test": "vitest run --config docs/.vitepress/vitest.config.js",
 		"build": "node build.js",
 		"build": "node build.js",
 		"lint": "prettier --cache --check . && eslint --cache . && stylelint web/css/src/**/*.css && markdownlint-cli2 *.md docs/**/*.md",
 		"lint": "prettier --cache --check . && eslint --cache . && stylelint web/css/src/**/*.css && markdownlint-cli2 *.md docs/**/*.md",
 		"lint-staged": "lint-staged",
 		"lint-staged": "lint-staged",
@@ -23,7 +24,7 @@
 		"chart.js": "^4.4.1",
 		"chart.js": "^4.4.1",
 		"check-password-strength": "^2.0.7",
 		"check-password-strength": "^2.0.7",
 		"floating-vue": "^5.2.2",
 		"floating-vue": "^5.2.2",
-		"nanoid": "^5.0.5",
+		"nanoid": "^5.0.6",
 		"normalize.css": "^8.0.1",
 		"normalize.css": "^8.0.1",
 		"xterm": "^5.3.0",
 		"xterm": "^5.3.0",
 		"xterm-addon-canvas": "^0.5.0",
 		"xterm-addon-canvas": "^0.5.0",
@@ -31,14 +32,17 @@
 	},
 	},
 	"devDependencies": {
 	"devDependencies": {
 		"@prettier/plugin-php": "^0.22.2",
 		"@prettier/plugin-php": "^0.22.2",
+		"@testing-library/vue": "^8.0.2",
+		"@vitejs/plugin-vue": "^5.0.4",
 		"browserslist": "^4.23.0",
 		"browserslist": "^4.23.0",
 		"esbuild": "^0.20.1",
 		"esbuild": "^0.20.1",
-		"eslint": "^8.56.0",
+		"eslint": "^8.57.0",
 		"eslint-config-prettier": "^9.1.0",
 		"eslint-config-prettier": "^9.1.0",
 		"eslint-plugin-editorconfig": "^4.0.3",
 		"eslint-plugin-editorconfig": "^4.0.3",
 		"eslint-plugin-import": "^2.29.1",
 		"eslint-plugin-import": "^2.29.1",
 		"husky": "^9.0.11",
 		"husky": "^9.0.11",
-		"lightningcss": "^1.23.0",
+		"jsdom": "^24.0.0",
+		"lightningcss": "^1.24.0",
 		"lint-staged": "^15.2.2",
 		"lint-staged": "^15.2.2",
 		"markdownlint-cli2": "^0.12.1",
 		"markdownlint-cli2": "^0.12.1",
 		"prettier": "^3.2.5",
 		"prettier": "^3.2.5",
@@ -47,8 +51,9 @@
 		"prettier-plugin-sql": "^0.18.0",
 		"prettier-plugin-sql": "^0.18.0",
 		"stylelint": "^16.2.1",
 		"stylelint": "^16.2.1",
 		"stylelint-config-standard": "^36.0.0",
 		"stylelint-config-standard": "^36.0.0",
-		"vitepress": "^1.0.0-rc.43",
-		"vue": "^3.4.19"
+		"vitepress": "^1.0.0-rc.44",
+		"vitest": "^1.3.1",
+		"vue": "^3.4.20"
 	},
 	},
 	"browserslist": [
 	"browserslist": [
 		"defaults"
 		"defaults"

+ 4 - 4
src/deb/web-terminal/package-lock.json

@@ -12,14 +12,14 @@
 				"ws": "^8.16.0"
 				"ws": "^8.16.0"
 			},
 			},
 			"devDependencies": {
 			"devDependencies": {
-				"@types/node": "^20.11.19",
+				"@types/node": "^20.11.20",
 				"@types/ws": "^8.5.10"
 				"@types/ws": "^8.5.10"
 			}
 			}
 		},
 		},
 		"node_modules/@types/node": {
 		"node_modules/@types/node": {
-			"version": "20.11.19",
-			"resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.19.tgz",
-			"integrity": "sha512-7xMnVEcZFu0DikYjWOlRq7NTPETrm7teqUT2WkQjrTIkEgUyyGdWsj/Zg8bEJt5TNklzbPD1X3fqfsHw3SpapQ==",
+			"version": "20.11.20",
+			"resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.20.tgz",
+			"integrity": "sha512-7/rR21OS+fq8IyHTgtLkDK949uzsa6n8BkziAKtPVpugIkO6D+/ooXMvzXxDnZrmtXVfjb1bKQafYpb8s89LOg==",
 			"dev": true,
 			"dev": true,
 			"dependencies": {
 			"dependencies": {
 				"undici-types": "~5.26.4"
 				"undici-types": "~5.26.4"

+ 1 - 1
src/deb/web-terminal/package.json

@@ -12,6 +12,6 @@
 	},
 	},
 	"devDependencies": {
 	"devDependencies": {
 		"@types/ws": "^8.5.10",
 		"@types/ws": "^8.5.10",
-		"@types/node": "^20.11.19"
+		"@types/node": "^20.11.20"
 	}
 	}
 }
 }

+ 1 - 1
web/templates/pages/list_web.php

@@ -44,7 +44,7 @@
 							<?php } ?>
 							<?php } ?>
 							<option value="suspend"><?= _("Suspend") ?></option>
 							<option value="suspend"><?= _("Suspend") ?></option>
 							<option value="unsuspend"><?= _("Unsuspend") ?></option>
 							<option value="unsuspend"><?= _("Unsuspend") ?></option>
-							<?php if ($_SESSION["PROXY_SYSTEM"] == "nginx" || $_SESSION["WEB_SYSTEM"] == "nginx") { ?>}
+							<?php if ($_SESSION["PROXY_SYSTEM"] == "nginx" || $_SESSION["WEB_SYSTEM"] == "nginx") { ?>
 								<option value="purge"><?= _("Purge Nginx Cache") ?></option>
 								<option value="purge"><?= _("Purge Nginx Cache") ?></option>
 							<?php } ?>
 							<?php } ?>
 							<option value="delete"><?= _("Delete") ?></option>
 							<option value="delete"><?= _("Delete") ?></option>

Some files were not shown because too many files changed in this diff