@networkpro/web 1.14.2 → 1.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +78 -1
- package/README.md +6 -4
- package/_redirects +4 -2
- package/cspell.json +2 -0
- package/netlify/edge-functions/csp-report.js +22 -15
- package/package.json +3 -4
- package/scripts/testRedirects.js +84 -0
- package/src/app.html +1 -1
- package/src/lib/components/RedirectPage.svelte +2 -34
- package/src/lib/components/layout/HeaderDefault.svelte +8 -3
- package/src/lib/components/layout/HeaderHome.svelte +8 -3
- package/src/lib/pages/AboutContent.svelte +1 -1
- package/src/lib/pages/HomeContent.svelte +3 -9
- package/src/lib/pages/LicenseContent.svelte +1 -2
- package/src/lib/pages/PrivacyContent.svelte +45 -31
- package/src/lib/pages/PrivacyDashboard.svelte +0 -1
- package/src/lib/pages/TermsConditionsContent.svelte +2 -2
- package/src/lib/stores/trackingPreferences.js +6 -0
- package/src/lib/styles/css/default.css +31 -4
- package/src/lib/styles/global.min.css +1 -1
- package/src/lib/utils/getUTMParams.js +43 -0
- package/src/lib/utils/purify.js +1 -1
- package/src/lib/utils/redirect.js +52 -0
- package/src/lib/utils/utm.js +31 -8
- package/src/routes/consultation/+page.svelte +16 -2
- package/src/routes/contact/+page.svelte +17 -3
- package/src/routes/links/+page.svelte +24 -5
- package/src/routes/posts/+page.svelte +24 -5
- package/src/routes/privacy-rights/+page.svelte +19 -3
- package/tests/unit/{unregisterServiceWorker.test.js → client/lib/unregisterServiceWorker.test.js} +2 -2
- package/tests/unit/client/lib/utils/redirect.test.js +80 -0
- package/tests/unit/client/lib/utils/utm.test.js +59 -0
- package/tests/unit/{routes → client/routes}/page.svelte.test.js +2 -2
- package/tests/unit/{checkEnv.test.js → server/checkEnv.test.js} +2 -2
- package/tests/unit/{checkVersions.test.js → server/checkVersions.test.js} +2 -2
- package/tests/unit/{csp-report.test.js → server/csp-report.test.js} +2 -2
- package/tests/{internal → unit/server/internal}/auditCoverage.test.js +13 -6
- package/tests/unit/{lib → server/lib}/utils/purify.test.js +2 -2
- package/vitest.config.client.js +1 -4
- package/vitest.config.server.js +1 -1
- package/tests/unit/utm.test.js +0 -49
package/tests/unit/{unregisterServiceWorker.test.js → client/lib/unregisterServiceWorker.test.js}
RENAMED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/* ==========================================================================
|
|
2
|
-
tests/unit/unregisterServiceWorker.test.js
|
|
2
|
+
tests/unit/client/lib/unregisterServiceWorker.test.js
|
|
3
3
|
|
|
4
4
|
Copyright © 2025 Network Pro Strategies (Network Pro™)
|
|
5
5
|
SPDX-License-Identifier: CC-BY-4.0 OR GPL-3.0-or-later
|
|
@@ -7,7 +7,7 @@ This file is part of Network Pro.
|
|
|
7
7
|
========================================================================== */
|
|
8
8
|
|
|
9
9
|
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
|
10
|
-
import { unregisterServiceWorker } from '
|
|
10
|
+
import { unregisterServiceWorker } from '../../../../src/lib/unregisterServiceWorker.js';
|
|
11
11
|
|
|
12
12
|
describe('unregisterServiceWorker()', () => {
|
|
13
13
|
beforeEach(() => {
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/* ==========================================================================
|
|
2
|
+
tests/unit/client/lib/utils/redirect.test.js
|
|
3
|
+
|
|
4
|
+
Copyright © 2025 Network Pro Strategies (Network Pro™)
|
|
5
|
+
SPDX-License-Identifier: CC-BY-4.0 OR GPL-3.0-or-later
|
|
6
|
+
This file is part of Network Pro.
|
|
7
|
+
========================================================================== */
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* @file redirect.test.js
|
|
11
|
+
* @description Unit test for src/lib/utils/redirect.js
|
|
12
|
+
* @module tests/unit/lib/util/
|
|
13
|
+
* @author SunDevil311
|
|
14
|
+
* @updated 2025-07-01
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
import { redirectWithBrowserAwareness } from '$lib/utils/redirect.js';
|
|
18
|
+
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
|
19
|
+
|
|
20
|
+
describe('redirectWithBrowserAwareness', () => {
|
|
21
|
+
let originalLocation;
|
|
22
|
+
let originalNavigator;
|
|
23
|
+
|
|
24
|
+
/** @type {{ url: string; delay: number }} */
|
|
25
|
+
const commonMocks = {
|
|
26
|
+
url: 'https://example.com',
|
|
27
|
+
delay: 1,
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
beforeEach(() => {
|
|
31
|
+
// Preserve globals
|
|
32
|
+
originalLocation = window.location;
|
|
33
|
+
originalNavigator = global.navigator;
|
|
34
|
+
|
|
35
|
+
// Stub window.location.replace
|
|
36
|
+
delete window.location;
|
|
37
|
+
window.location = {
|
|
38
|
+
replace: vi.fn(),
|
|
39
|
+
};
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
afterEach(() => {
|
|
43
|
+
// Restore globals
|
|
44
|
+
window.location = originalLocation;
|
|
45
|
+
global.navigator = originalNavigator;
|
|
46
|
+
vi.clearAllMocks();
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
it('should redirect immediately in Firefox', () => {
|
|
50
|
+
global.navigator = {
|
|
51
|
+
userAgent:
|
|
52
|
+
'Mozilla/5.0 (Windows NT 10.0; rv:99.0) Gecko/20100101 Firefox/99.0',
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
redirectWithBrowserAwareness(commonMocks.url, commonMocks.delay);
|
|
56
|
+
|
|
57
|
+
expect(window.location.replace).toHaveBeenCalledWith(commonMocks.url);
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
it('should redirect after delay in non-Firefox', () => {
|
|
61
|
+
vi.useFakeTimers();
|
|
62
|
+
|
|
63
|
+
global.navigator = {
|
|
64
|
+
userAgent:
|
|
65
|
+
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0 Safari/537.36',
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
redirectWithBrowserAwareness(commonMocks.url, commonMocks.delay);
|
|
69
|
+
|
|
70
|
+
expect(window.location.replace).not.toHaveBeenCalled();
|
|
71
|
+
|
|
72
|
+
vi.advanceTimersByTime(commonMocks.delay * 1000);
|
|
73
|
+
|
|
74
|
+
expect(window.location.replace).toHaveBeenCalledWith(commonMocks.url);
|
|
75
|
+
|
|
76
|
+
vi.useRealTimers();
|
|
77
|
+
});
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
// cspell:ignore khtml
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/* ==========================================================================
|
|
2
|
+
tests/unit/client/lib/utils/utm.test.js
|
|
3
|
+
|
|
4
|
+
Copyright © 2025 Network Pro Strategies (Network Pro™)
|
|
5
|
+
SPDX-License-Identifier: CC-BY-4.0 OR GPL-3.0-or-later
|
|
6
|
+
This file is part of Network Pro.
|
|
7
|
+
========================================================================== */
|
|
8
|
+
|
|
9
|
+
// Mock SvelteKit environment and store
|
|
10
|
+
vi.mock('$app/environment', () => ({ browser: true }));
|
|
11
|
+
|
|
12
|
+
import { writable } from 'svelte/store';
|
|
13
|
+
|
|
14
|
+
vi.mock('$app/stores', () => {
|
|
15
|
+
const mockPageStore = writable({
|
|
16
|
+
url: {
|
|
17
|
+
pathname: '/contact',
|
|
18
|
+
},
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
return {
|
|
22
|
+
getStores: () => ({
|
|
23
|
+
page: mockPageStore,
|
|
24
|
+
}),
|
|
25
|
+
};
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
import { appendUTM } from '$lib/utils/utm.js';
|
|
29
|
+
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
|
30
|
+
|
|
31
|
+
describe('appendUTM', () => {
|
|
32
|
+
const originalWindow = globalThis.window;
|
|
33
|
+
|
|
34
|
+
beforeEach(() => {
|
|
35
|
+
globalThis.window = {
|
|
36
|
+
location: { search: '' },
|
|
37
|
+
};
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
afterEach(() => {
|
|
41
|
+
globalThis.window = originalWindow;
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
it('should return URL with utm parameters for /contact', () => {
|
|
45
|
+
const url = 'https://example.com';
|
|
46
|
+
const result = appendUTM(url);
|
|
47
|
+
expect(result).toBe(
|
|
48
|
+
'https://example.com?utm_source=netwk.pro&utm_medium=redirect&utm_campaign=contact',
|
|
49
|
+
);
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
it('should append using & if URL already has query params', () => {
|
|
53
|
+
const url = 'https://example.com?existing=value';
|
|
54
|
+
const result = appendUTM(url);
|
|
55
|
+
expect(result).toBe(
|
|
56
|
+
'https://example.com?existing=value&utm_source=netwk.pro&utm_medium=redirect&utm_campaign=contact',
|
|
57
|
+
);
|
|
58
|
+
});
|
|
59
|
+
});
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/* ==========================================================================
|
|
2
|
-
tests/unit/routes/page.svelte.test.js
|
|
2
|
+
tests/unit/client/routes/page.svelte.test.js
|
|
3
3
|
|
|
4
4
|
Copyright © 2025 Network Pro Strategies (Network Pro™)
|
|
5
5
|
SPDX-License-Identifier: CC-BY-4.0 OR GPL-3.0-or-later
|
|
@@ -9,7 +9,7 @@ This file is part of Network Pro.
|
|
|
9
9
|
import '@testing-library/jest-dom/vitest';
|
|
10
10
|
import { render, screen } from '@testing-library/svelte';
|
|
11
11
|
import { describe, expect, test } from 'vitest';
|
|
12
|
-
import Page from '
|
|
12
|
+
import Page from '../../../../src/routes/+page.svelte';
|
|
13
13
|
|
|
14
14
|
describe('/+page.svelte', () => {
|
|
15
15
|
test('should render the home page section', () => {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/* ==========================================================================
|
|
2
|
-
tests/unit/checkEnv.test.js
|
|
2
|
+
tests/unit/server/checkEnv.test.js
|
|
3
3
|
|
|
4
4
|
Copyright © 2025 Network Pro Strategies (Network Pro™)
|
|
5
5
|
SPDX-License-Identifier: CC-BY-4.0 OR GPL-3.0-or-later
|
|
@@ -11,7 +11,7 @@ This file is part of Network Pro.
|
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
13
|
import { afterEach, describe, expect, it } from 'vitest';
|
|
14
|
-
import { checkEnv } from '
|
|
14
|
+
import { checkEnv } from '../../../scripts/checkEnv.js';
|
|
15
15
|
|
|
16
16
|
describe('checkEnv()', () => {
|
|
17
17
|
const originalEnv = process.env.ENV_MODE;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/* ==========================================================================
|
|
2
|
-
tests/unit/checkVersions.test.js
|
|
2
|
+
tests/unit/server/checkVersions.test.js
|
|
3
3
|
|
|
4
4
|
Copyright © 2025 Network Pro Strategies (Network Pro™)
|
|
5
5
|
SPDX-License-Identifier: CC-BY-4.0 OR GPL-3.0-or-later
|
|
@@ -11,7 +11,7 @@ This file is part of Network Pro.
|
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
13
|
import { describe, expect, it } from 'vitest';
|
|
14
|
-
import { checkVersions } from '
|
|
14
|
+
import { checkVersions } from '../../../scripts/checkVersions.js';
|
|
15
15
|
|
|
16
16
|
describe('checkVersions()', () => {
|
|
17
17
|
it('should match current Node and NPM versions to engine ranges', () => {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/* ==========================================================================
|
|
2
|
-
tests/unit/csp-report.test.js
|
|
2
|
+
tests/unit/server/csp-report.test.js
|
|
3
3
|
|
|
4
4
|
Copyright © 2025 Network Pro Strategies (Network Pro™)
|
|
5
5
|
SPDX-License-Identifier: CC-BY-4.0 OR GPL-3.0-or-later
|
|
@@ -18,7 +18,7 @@ This file is part of Network Pro.
|
|
|
18
18
|
/** @typedef {import('vitest').TestContext} TestContext */
|
|
19
19
|
|
|
20
20
|
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
|
21
|
-
import handler from '
|
|
21
|
+
import handler from '../../../netlify/edge-functions/csp-report.js';
|
|
22
22
|
|
|
23
23
|
// 🧪 Mock fetch used by sendToNtfy inside the Edge Function
|
|
24
24
|
global.fetch = vi.fn(() =>
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/* ==========================================================================
|
|
2
|
-
tests/internal/auditCoverage.test.js
|
|
2
|
+
tests/unit/server/internal/auditCoverage.test.js
|
|
3
3
|
|
|
4
4
|
Copyright © 2025 Network Pro Strategies (Network Pro™)
|
|
5
5
|
SPDX-License-Identifier: CC-BY-4.0 OR GPL-3.0-or-later
|
|
@@ -8,10 +8,11 @@ This file is part of Network Pro.
|
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
10
|
* @file auditCoverage.test.js
|
|
11
|
-
* @description Scans all .js files in src/ and scripts/ for matching unit
|
|
11
|
+
* @description Scans all .js files in src/ and scripts/ for matching unit
|
|
12
|
+
* tests
|
|
12
13
|
* @module tests/internal
|
|
13
14
|
* @author SunDevil311
|
|
14
|
-
* @updated 2025-
|
|
15
|
+
* @updated 2025-07-01
|
|
15
16
|
*/
|
|
16
17
|
|
|
17
18
|
import fs from 'fs';
|
|
@@ -60,20 +61,26 @@ describe('auditCoverage', () => {
|
|
|
60
61
|
const allFiles = [...srcFiles, ...scriptsFiles].map((f) =>
|
|
61
62
|
path
|
|
62
63
|
.relative(process.cwd(), f)
|
|
63
|
-
.replace(/\\/g, '/')
|
|
64
|
+
.replace(/\\/g, '/')
|
|
64
65
|
.replace(/^src\//, '')
|
|
65
66
|
.replace(/^scripts\//, '')
|
|
66
67
|
.replace(/\.js$/, ''),
|
|
67
68
|
);
|
|
68
69
|
|
|
69
|
-
const
|
|
70
|
+
const clientTests = getAllJsFiles(path.resolve('tests/unit/client'), {
|
|
71
|
+
includeTests: true,
|
|
72
|
+
});
|
|
73
|
+
const serverTests = getAllJsFiles(path.resolve('tests/unit/server'), {
|
|
70
74
|
includeTests: true,
|
|
71
75
|
});
|
|
76
|
+
const testFiles = [...clientTests, ...serverTests];
|
|
72
77
|
|
|
73
78
|
const testFilesNormalized = testFiles.map((f) =>
|
|
74
79
|
path
|
|
75
|
-
.relative(
|
|
80
|
+
.relative(process.cwd(), f)
|
|
76
81
|
.replace(/\\/g, '/')
|
|
82
|
+
.replace(/^tests\/unit\/client\//, '')
|
|
83
|
+
.replace(/^tests\/unit\/server\//, '')
|
|
77
84
|
.replace(/\.test\.js$|\.spec\.js$/, ''),
|
|
78
85
|
);
|
|
79
86
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/* ==========================================================================
|
|
2
|
-
tests/unit/lib/utils/purify.test.js
|
|
2
|
+
tests/unit/server/lib/utils/purify.test.js
|
|
3
3
|
|
|
4
4
|
Copyright © 2025 Network Pro Strategies (Network Pro™)
|
|
5
5
|
SPDX-License-Identifier: CC-BY-4.0 OR GPL-3.0-or-later
|
|
@@ -15,7 +15,7 @@ This file is part of Network Pro.
|
|
|
15
15
|
*/
|
|
16
16
|
|
|
17
17
|
import { describe, expect, it } from 'vitest';
|
|
18
|
-
import { sanitizeHtml } from '
|
|
18
|
+
import { sanitizeHtml } from '../../../../../src/lib/utils/purify.js';
|
|
19
19
|
|
|
20
20
|
describe('sanitizeHtml', () => {
|
|
21
21
|
it('removes dangerous tags like <script>', async () => {
|
package/vitest.config.client.js
CHANGED
|
@@ -26,10 +26,7 @@ export default defineConfig({
|
|
|
26
26
|
name: 'client',
|
|
27
27
|
environment: 'jsdom',
|
|
28
28
|
clearMocks: true,
|
|
29
|
-
include: [
|
|
30
|
-
'tests/unit/**/*.test.{js,mjs,svelte}',
|
|
31
|
-
'tests/internal/**/*.test.{js,mjs,svelte}',
|
|
32
|
-
],
|
|
29
|
+
include: ['tests/unit/client/**/*.test.{js,mjs,svelte}'],
|
|
33
30
|
exclude: [],
|
|
34
31
|
setupFiles: ['./vitest-setup-client.js'],
|
|
35
32
|
reporters: ['default', 'json'],
|
package/vitest.config.server.js
CHANGED
|
@@ -23,7 +23,7 @@ export default defineConfig({
|
|
|
23
23
|
test: {
|
|
24
24
|
name: 'server',
|
|
25
25
|
environment: 'node',
|
|
26
|
-
include: ['tests/unit/**/*.test.{js,mjs}'],
|
|
26
|
+
include: ['tests/unit/server/**/*.test.{js,mjs}'],
|
|
27
27
|
exclude: ['tests/unit/**/*.svelte.test.{js,mjs}'],
|
|
28
28
|
reporters: ['default', 'json'],
|
|
29
29
|
testTimeout: 10000,
|
package/tests/unit/utm.test.js
DELETED
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
/* ==========================================================================
|
|
2
|
-
tests/unit/utm.test.js
|
|
3
|
-
|
|
4
|
-
Copyright © 2025 Network Pro Strategies (Network Pro™)
|
|
5
|
-
SPDX-License-Identifier: CC-BY-4.0 OR GPL-3.0-or-later
|
|
6
|
-
This file is part of Network Pro.
|
|
7
|
-
========================================================================== */
|
|
8
|
-
|
|
9
|
-
import { appendUTM } from '$lib/utils/utm.js';
|
|
10
|
-
import { afterEach, describe, expect, it } from 'vitest';
|
|
11
|
-
|
|
12
|
-
describe('appendUTM', () => {
|
|
13
|
-
const originalWindow = globalThis.window;
|
|
14
|
-
|
|
15
|
-
afterEach(() => {
|
|
16
|
-
globalThis.window = originalWindow;
|
|
17
|
-
});
|
|
18
|
-
|
|
19
|
-
it('should return null when not in a browser environment', () => {
|
|
20
|
-
// @ts-expect-error – simulating SSR
|
|
21
|
-
delete globalThis.window;
|
|
22
|
-
|
|
23
|
-
const url = 'https://example.com';
|
|
24
|
-
const result = appendUTM(url);
|
|
25
|
-
expect(result).toBe(null);
|
|
26
|
-
});
|
|
27
|
-
|
|
28
|
-
it('should return URL with utm_source appended', () => {
|
|
29
|
-
globalThis.window = {
|
|
30
|
-
// @ts-expect-error – mock minimal window for test
|
|
31
|
-
location: { search: '?utm_source=linkedin' },
|
|
32
|
-
};
|
|
33
|
-
|
|
34
|
-
const url = 'https://example.com';
|
|
35
|
-
const result = appendUTM(url);
|
|
36
|
-
expect(result).toBe('https://example.com?utm_source=linkedin');
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
it('should return original URL if no utm_source is present', () => {
|
|
40
|
-
globalThis.window = {
|
|
41
|
-
// @ts-expect-error – mock minimal window for test
|
|
42
|
-
location: { search: '' },
|
|
43
|
-
};
|
|
44
|
-
|
|
45
|
-
const url = 'https://example.com';
|
|
46
|
-
const result = appendUTM(url);
|
|
47
|
-
expect(result).toBe('https://example.com');
|
|
48
|
-
});
|
|
49
|
-
});
|