diff --git a/Makefile b/Makefile new file mode 100644 index 00000000..fb4154f6 --- /dev/null +++ b/Makefile @@ -0,0 +1,11 @@ +VERSION = $(shell jq -r '.version' package.json) + +docker-build: + docker build --tag zonemaster/all-in-one:local --build-arg version=$(VERSION) -f docker/Dockerfile . + +docker-tag-version: + docker tag zonemaster/all-in-one:local zonemaster/all-in-one:$(VERSION) + +docker-tag-latest: + docker tag zonemaster/all-in-one:local zonemaster/all-in-one:latest + diff --git a/docker/Dockerfile b/docker/Dockerfile new file mode 100644 index 00000000..cf39d706 --- /dev/null +++ b/docker/Dockerfile @@ -0,0 +1,38 @@ +############################################################ +## Zonemaster All-In-One docker image +## +## DO NOT USE THIS IMAGE IN PRODUCTION +## +############################################################ +FROM zonemaster/backend:local + +ARG version + +EXPOSE 80 + +USER root +COPY ./zonemaster_web_gui_${version}.zip . + +RUN apk add apache2 apache2-proxy + +RUN install -vd /var/www/html/zonemaster-web-gui /var/log/zonemaster && \ + unzip -d /var/www/html/zonemaster-web-gui zonemaster_web_gui_${version}.zip && \ + rm -f zonemaster_web_gui_${version}.zip + +# Enable apache module +RUN echo "LoadModule rewrite_module modules/mod_rewrite.so" >> /etc/apache2/httpd.conf +RUN echo "LoadModule proxy_module modules/mod_proxy.so" >> /etc/apache2/httpd.conf +RUN echo "LoadModule proxy_http_module modules/mod_proxy_http.so" >> /etc/apache2/httpd.conf +RUN cat /var/www/html/zonemaster-web-gui/zonemaster.conf-example >> /etc/apache2/httpd.conf + +# HTTP service +RUN mkdir /etc/s6-overlay/s6-rc.d/httpd +RUN echo "longrun" > /etc/s6-overlay/s6-rc.d/httpd/type +RUN echo "#!/command/execlineb -P" > /etc/s6-overlay/s6-rc.d/httpd/run +RUN echo "httpd -DFOREGROUND" >> /etc/s6-overlay/s6-rc.d/httpd/run + +RUN touch /etc/s6-overlay/s6-rc.d/user/contents.d/httpd + +COPY docker/zonemaster_launch_gui /usr/local/bin + +ENTRYPOINT ["/usr/local/bin/zonemaster_launch_gui"] diff --git a/docker/zonemaster_launch_gui b/docker/zonemaster_launch_gui new file mode 100755 index 00000000..18b43471 --- /dev/null +++ b/docker/zonemaster_launch_gui @@ -0,0 +1,12 @@ +#!/bin/sh + +case $1 in + gui) + exec /init + ;; + + *) + # pass the argument to zonemaster_launch from zonemaster-backend Docker image + zonemaster_launch $@ + ;; +esac; diff --git a/e2e/FR11.e2e-spec.ts-snapshots/domain-chromium-linux.png b/e2e/FR11.e2e-spec.ts-snapshots/domain-chromium-linux.png index c38b43e4..bc7408dd 100644 Binary files a/e2e/FR11.e2e-spec.ts-snapshots/domain-chromium-linux.png and b/e2e/FR11.e2e-spec.ts-snapshots/domain-chromium-linux.png differ diff --git a/e2e/FR11.e2e-spec.ts-snapshots/domain-options-chromium-linux.png b/e2e/FR11.e2e-spec.ts-snapshots/domain-options-chromium-linux.png index 59b6a7c8..eabb824f 100644 Binary files a/e2e/FR11.e2e-spec.ts-snapshots/domain-options-chromium-linux.png and b/e2e/FR11.e2e-spec.ts-snapshots/domain-options-chromium-linux.png differ diff --git a/e2e/FR21.e2e-spec.ts-snapshots/results-chromium-linux.png b/e2e/FR21.e2e-spec.ts-snapshots/results-chromium-linux.png index 69074e5f..a0303d15 100644 Binary files a/e2e/FR21.e2e-spec.ts-snapshots/results-chromium-linux.png and b/e2e/FR21.e2e-spec.ts-snapshots/results-chromium-linux.png differ diff --git a/e2e/FR26.e2e-spec.ts b/e2e/FR26.e2e-spec.ts new file mode 100644 index 00000000..0fa27f1e --- /dev/null +++ b/e2e/FR26.e2e-spec.ts @@ -0,0 +1,24 @@ +import { test, expect } from './global-setup'; + +test.describe('Zonemaster test FR26 - [Shows results with empty testcases]', () => { + test('shows a result with an empty testcase', async ({ + page, + }) => { + await page.goto('/en/result/empty-testcase-response/'); + + await expect(page.locator('.zm-result')).toBeVisible({ + timeout: 10000, + }); + await expect( + page.getByRole('heading', { + name: 'Test result for empty-testcase.example', + }), + ).toBeVisible(); + + await page.getByRole('button', { name: 'Expand all modules' }).click(); + + await expect(page.locator('#zmModule-Backend-content')).toContainText( + 'The backend returned a result without a testcase.', + ); + }); +}); diff --git a/e2e/interceptors/mock.interceptor.ts b/e2e/interceptors/mock.interceptor.ts index 81f1d39e..1d69fa1d 100644 --- a/e2e/interceptors/mock.interceptor.ts +++ b/e2e/interceptors/mock.interceptor.ts @@ -40,7 +40,6 @@ const urls: MockEndpoint[] = [ }, // FR18 - Should display progress bar - // FR26 - Should display progress bar { url: 'http://localhost:4321/api', body: {'jsonrpc': '2.0', 'id': 1572254767685, 'method': 'start_domain_test', 'params': @@ -113,7 +112,6 @@ const urls: MockEndpoint[] = [ // FR18 - Should display progress bar // FR19 - Should display progress bar when we add a NS name // FR20 - should display progress bar when we add a DS entry and launch a test - // FR26 - Should display progress bar { url: 'http://localhost:4321/api', body: {'jsonrpc': '2.0', 'id': 1572254972236, 'method': 'test_progress', 'params': {'test_id': '2005cf23e9fb24b6'}}, @@ -883,6 +881,39 @@ const urls: MockEndpoint[] = [ } } }, + // Result returned without a testcase. + { + url: 'http://localhost:4321/api', + body: {'jsonrpc': '2.0', 'id': 1, 'method': 'get_test_results', 'params': {'id': 'empty-testcase-response', 'language': 'en'}}, + method: 'POST', + json: {'jsonrpc': '2.0', 'id': 1, 'result': { + 'results': [ + { + 'level': 'CRITICAL', + 'testcase': '', + 'module': 'Backend', + 'message': 'The backend returned a result without a testcase.\n' + } + ], + 'params': { + 'profile': 'default', + 'ipv6': true, + 'ds_info': [], + 'language': 'en', + 'priority': 10, + 'queue': 0, + 'client_id': 'Zonemaster-GUI', + 'ipv4': true, + 'domain': 'empty-testcase.example', + 'nameservers': [], + 'client_version': 'v5.0.1' + }, + 'testcase_descriptions': {'': ''}, + 'created_at': '2026-04-02T11:15:15Z', + 'hash_id': 'empty-testcase-response' + } + } + }, // FR23 - Should display previous tests // FR24 - Should display previous run link diff --git a/src/lib/groupResult.ts b/src/lib/groupResult.ts index 9f327905..0ddc9924 100644 --- a/src/lib/groupResult.ts +++ b/src/lib/groupResult.ts @@ -25,7 +25,7 @@ export function groupResult(results: ResultDataResult[]) { for (const entry of results) { const currentModule = entry.module; - const currentTestcase = entry.testcase; + const currentTestcase = entry.testcase || 'Unspecified'; const currentLevel = entry.level; const numLevel = severityLevels[entry.level]; diff --git a/src/lib/niceName.ts b/src/lib/niceName.ts index 81252dd2..08f5cf07 100644 --- a/src/lib/niceName.ts +++ b/src/lib/niceName.ts @@ -1,5 +1,9 @@ // Lowercase and capitalize export default function niceName(name: string): string { + if (!name) { + return ''; + } + const [first, ...rest] = name.toLowerCase(); return first.toUpperCase() + rest.join(''); diff --git a/this-file-should-not-be-included.txt b/this-file-should-not-be-included.txt new file mode 100644 index 00000000..ec9d8a7a --- /dev/null +++ b/this-file-should-not-be-included.txt @@ -0,0 +1 @@ +this-file-should-not-be-included