@verdaccio/web 6.0.0-6-next.27 → 6.0.0-6-next.30
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 +71 -0
- package/build/api/index.js.map +1 -1
- package/build/api/package.d.ts +1 -8
- package/build/api/package.js +51 -54
- package/build/api/package.js.map +1 -1
- package/build/api/readme.d.ts +2 -2
- package/build/api/readme.js +25 -20
- package/build/api/readme.js.map +1 -1
- package/build/api/search.js +1 -3
- package/build/api/search.js.map +1 -1
- package/build/api/sidebar.d.ts +3 -3
- package/build/api/sidebar.js +46 -39
- package/build/api/sidebar.js.map +1 -1
- package/build/api/user.js.map +1 -1
- package/build/index.js.map +1 -1
- package/build/middleware/render-web.js.map +1 -1
- package/build/middleware/security.js.map +1 -1
- package/build/middleware/web-api.js.map +1 -1
- package/build/renderHTML.js +27 -14
- package/build/renderHTML.js.map +1 -1
- package/build/template.js.map +1 -1
- package/build/utils/manifest.js.map +1 -1
- package/build/utils/web-utils.js +1 -1
- package/build/utils/web-utils.js.map +1 -1
- package/build/web-middleware.js.map +1 -1
- package/jest.config.js +8 -1
- package/package.json +70 -69
- package/src/api/package.ts +53 -54
- package/src/api/readme.ts +33 -24
- package/src/api/search.ts +1 -1
- package/src/api/sidebar.ts +51 -39
- package/src/renderHTML.ts +25 -8
- package/src/utils/web-utils.ts +1 -1
- package/test/api.readme.test.ts +1 -1
- package/test/config/web.yaml +46 -0
- package/test/render.test.ts +71 -24
- package/test/utils.spec.ts +10 -1
- package/tsconfig.json +0 -3
package/src/api/readme.ts
CHANGED
|
@@ -6,13 +6,14 @@ import { HEADERS, HEADER_TYPE } from '@verdaccio/core';
|
|
|
6
6
|
import { $NextFunctionVer, $RequestExtend, $ResponseExtend, allow } from '@verdaccio/middleware';
|
|
7
7
|
import sanitizyReadme from '@verdaccio/readme';
|
|
8
8
|
import { Storage } from '@verdaccio/store';
|
|
9
|
-
import {
|
|
9
|
+
import { Manifest } from '@verdaccio/types';
|
|
10
10
|
|
|
11
11
|
import { AuthorAvatar, addScope, parseReadme } from '../utils/web-utils';
|
|
12
12
|
|
|
13
13
|
export { $RequestExtend, $ResponseExtend, $NextFunctionVer }; // Was required by other packages
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
// TODO: review this type, should be on @verdacid/types
|
|
16
|
+
export type PackageExt = Manifest & { author: AuthorAvatar; dist?: { tarball: string } };
|
|
16
17
|
|
|
17
18
|
const debug = buildDebug('verdaccio:web:api:readme');
|
|
18
19
|
|
|
@@ -26,31 +27,39 @@ function addReadmeWebApi(storage: Storage, auth: IAuth): Router {
|
|
|
26
27
|
pkgRouter.get(
|
|
27
28
|
'/package/readme/(@:scope/)?:package/:version?',
|
|
28
29
|
can('access'),
|
|
29
|
-
function (
|
|
30
|
+
async function (
|
|
31
|
+
req: $RequestExtend,
|
|
32
|
+
res: $ResponseExtend,
|
|
33
|
+
next: $NextFunctionVer
|
|
34
|
+
): Promise<void> {
|
|
30
35
|
debug('readme hit');
|
|
31
|
-
const
|
|
36
|
+
const name = req.params.scope
|
|
32
37
|
? addScope(req.params.scope, req.params.package)
|
|
33
38
|
: req.params.package;
|
|
34
|
-
debug('readme name %o',
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
req,
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
}
|
|
53
|
-
|
|
39
|
+
debug('readme name %o', name);
|
|
40
|
+
const requestOptions = {
|
|
41
|
+
protocol: req.protocol,
|
|
42
|
+
headers: req.headers as any,
|
|
43
|
+
// FIXME: if we migrate to req.hostname, the port is not longer included.
|
|
44
|
+
host: req.host,
|
|
45
|
+
remoteAddress: req.socket.remoteAddress,
|
|
46
|
+
};
|
|
47
|
+
try {
|
|
48
|
+
const manifest = await storage.getPackageByOptions({
|
|
49
|
+
name,
|
|
50
|
+
uplinksLook: true,
|
|
51
|
+
requestOptions,
|
|
52
|
+
});
|
|
53
|
+
debug('readme pkg %o', manifest?.name);
|
|
54
|
+
res.set(HEADER_TYPE.CONTENT_TYPE, HEADERS.TEXT_PLAIN_UTF8);
|
|
55
|
+
try {
|
|
56
|
+
next(parseReadme(manifest.name, manifest.readme as string));
|
|
57
|
+
} catch {
|
|
58
|
+
next(sanitizyReadme(NOT_README_FOUND));
|
|
59
|
+
}
|
|
60
|
+
} catch (err) {
|
|
61
|
+
next(err);
|
|
62
|
+
}
|
|
54
63
|
}
|
|
55
64
|
);
|
|
56
65
|
return pkgRouter;
|
package/src/api/search.ts
CHANGED
|
@@ -64,7 +64,7 @@ function addSearchWebApi(storage: Storage, auth: IAuth): Router {
|
|
|
64
64
|
// @ts-ignore
|
|
65
65
|
const urlParams = new URLSearchParams(query);
|
|
66
66
|
debug('search web init');
|
|
67
|
-
data = await storage
|
|
67
|
+
data = await storage?.search({
|
|
68
68
|
query,
|
|
69
69
|
url: `/-/v1/search?${urlParams.toString()}`,
|
|
70
70
|
abort,
|
package/src/api/sidebar.ts
CHANGED
|
@@ -1,22 +1,21 @@
|
|
|
1
1
|
import buildDebug from 'debug';
|
|
2
2
|
import { Router } from 'express';
|
|
3
|
-
import _ from 'lodash';
|
|
4
3
|
|
|
5
4
|
import { IAuth } from '@verdaccio/auth';
|
|
6
5
|
import { DIST_TAGS, HTTP_STATUS } from '@verdaccio/core';
|
|
7
6
|
import { $NextFunctionVer, $RequestExtend, $ResponseExtend, allow } from '@verdaccio/middleware';
|
|
8
7
|
import { Storage } from '@verdaccio/store';
|
|
9
8
|
import { convertDistRemoteToLocalTarballUrls } from '@verdaccio/tarball';
|
|
10
|
-
import { Config,
|
|
9
|
+
import { Config, Manifest, Version } from '@verdaccio/types';
|
|
11
10
|
import { addGravatarSupport, formatAuthor, isVersionValid } from '@verdaccio/utils';
|
|
12
11
|
|
|
13
12
|
import { AuthorAvatar, addScope, deleteProperties } from '../utils/web-utils';
|
|
14
13
|
|
|
15
14
|
export { $RequestExtend, $ResponseExtend, $NextFunctionVer }; // Was required by other packages
|
|
16
15
|
|
|
17
|
-
export type PackageExt =
|
|
16
|
+
export type PackageExt = Manifest & { author: AuthorAvatar; dist?: { tarball: string } };
|
|
18
17
|
|
|
19
|
-
export type $SidebarPackage =
|
|
18
|
+
export type $SidebarPackage = Manifest & { latest: Version };
|
|
20
19
|
const debug = buildDebug('verdaccio:web:api:sidebar');
|
|
21
20
|
|
|
22
21
|
function addSidebarWebApi(config: Config, storage: Storage, auth: IAuth): Router {
|
|
@@ -27,43 +26,56 @@ function addSidebarWebApi(config: Config, storage: Storage, auth: IAuth): Router
|
|
|
27
26
|
router.get(
|
|
28
27
|
'/sidebar/(@:scope/)?:package',
|
|
29
28
|
can('access'),
|
|
30
|
-
function (
|
|
31
|
-
|
|
29
|
+
async function (
|
|
30
|
+
req: $RequestExtend,
|
|
31
|
+
res: $ResponseExtend,
|
|
32
|
+
next: $NextFunctionVer
|
|
33
|
+
): Promise<void> {
|
|
34
|
+
const name: string = req.params.scope
|
|
32
35
|
? addScope(req.params.scope, req.params.package)
|
|
33
36
|
: req.params.package;
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
req,
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
37
|
+
const requestOptions = {
|
|
38
|
+
protocol: req.protocol,
|
|
39
|
+
headers: req.headers as any,
|
|
40
|
+
// FIXME: if we migrate to req.hostname, the port is not longer included.
|
|
41
|
+
host: req.host,
|
|
42
|
+
remoteAddress: req.socket.remoteAddress,
|
|
43
|
+
};
|
|
44
|
+
try {
|
|
45
|
+
const info = (await storage.getPackageByOptions({
|
|
46
|
+
name,
|
|
47
|
+
uplinksLook: true,
|
|
48
|
+
keepUpLinkData: true,
|
|
49
|
+
requestOptions,
|
|
50
|
+
})) as Manifest;
|
|
51
|
+
const { v } = req.query;
|
|
52
|
+
let sideBarInfo = { ...info };
|
|
53
|
+
sideBarInfo.versions = convertDistRemoteToLocalTarballUrls(
|
|
54
|
+
info,
|
|
55
|
+
{ protocol: req.protocol, headers: req.headers as any, host: req.hostname },
|
|
56
|
+
config.url_prefix
|
|
57
|
+
).versions;
|
|
58
|
+
// TODO: review this implementation
|
|
59
|
+
if (typeof v === 'string' && isVersionValid(info, v)) {
|
|
60
|
+
// @ts-ignore
|
|
61
|
+
sideBarInfo.latest = sideBarInfo.versions[v];
|
|
62
|
+
// @ts-ignore
|
|
63
|
+
sideBarInfo.latest.author = formatAuthor(sideBarInfo.latest.author);
|
|
64
|
+
} else {
|
|
65
|
+
// @ts-ignore
|
|
66
|
+
sideBarInfo.latest = sideBarInfo.versions[info[DIST_TAGS].latest];
|
|
67
|
+
// @ts-ignore
|
|
68
|
+
sideBarInfo.latest.author = formatAuthor(sideBarInfo.latest.author);
|
|
69
|
+
}
|
|
70
|
+
sideBarInfo = deleteProperties(['readme', '_attachments', '_rev', 'name'], sideBarInfo);
|
|
71
|
+
const authorAvatar = config.web
|
|
72
|
+
? addGravatarSupport(sideBarInfo, config.web.gravatar)
|
|
73
|
+
: addGravatarSupport(sideBarInfo);
|
|
74
|
+
next(authorAvatar);
|
|
75
|
+
} catch (err) {
|
|
76
|
+
res.status(HTTP_STATUS.NOT_FOUND);
|
|
77
|
+
res.end();
|
|
78
|
+
}
|
|
67
79
|
}
|
|
68
80
|
);
|
|
69
81
|
|
package/src/renderHTML.ts
CHANGED
|
@@ -26,6 +26,9 @@ export default function renderHTML(config, manifest, manifestFiles, req, res) {
|
|
|
26
26
|
const base = getPublicUrl(config?.url_prefix, req);
|
|
27
27
|
const basename = new URL(base).pathname;
|
|
28
28
|
const language = config?.i18n?.web ?? DEFAULT_LANGUAGE;
|
|
29
|
+
const needHtmlCache = [undefined, null].includes(config?.web?.html_cache)
|
|
30
|
+
? true
|
|
31
|
+
: config.web.html_cache;
|
|
29
32
|
const darkMode = config?.web?.darkMode ?? false;
|
|
30
33
|
const title = config?.web?.title ?? WEB_TITLE;
|
|
31
34
|
const login = hasLogin(config);
|
|
@@ -37,7 +40,17 @@ export default function renderHTML(config, manifest, manifestFiles, req, res) {
|
|
|
37
40
|
...config.flags,
|
|
38
41
|
};
|
|
39
42
|
const primaryColor = validatePrimaryColor(config?.web?.primary_color) ?? '#4b5e40';
|
|
40
|
-
const {
|
|
43
|
+
const {
|
|
44
|
+
scriptsBodyAfter,
|
|
45
|
+
metaScripts,
|
|
46
|
+
scriptsbodyBefore,
|
|
47
|
+
showInfo,
|
|
48
|
+
showSettings,
|
|
49
|
+
showThemeSwitch,
|
|
50
|
+
showFooter,
|
|
51
|
+
showSearch,
|
|
52
|
+
showDownloadTarball,
|
|
53
|
+
} = Object.assign(
|
|
41
54
|
{},
|
|
42
55
|
{
|
|
43
56
|
scriptsBodyAfter: [],
|
|
@@ -47,6 +60,12 @@ export default function renderHTML(config, manifest, manifestFiles, req, res) {
|
|
|
47
60
|
config?.web
|
|
48
61
|
);
|
|
49
62
|
const options: TemplateUIOptions = {
|
|
63
|
+
showInfo,
|
|
64
|
+
showSettings,
|
|
65
|
+
showThemeSwitch,
|
|
66
|
+
showFooter,
|
|
67
|
+
showSearch,
|
|
68
|
+
showDownloadTarball,
|
|
50
69
|
darkMode,
|
|
51
70
|
url_prefix,
|
|
52
71
|
basename,
|
|
@@ -66,10 +85,7 @@ export default function renderHTML(config, manifest, manifestFiles, req, res) {
|
|
|
66
85
|
|
|
67
86
|
try {
|
|
68
87
|
webPage = cache.get('template');
|
|
69
|
-
|
|
70
88
|
if (!webPage) {
|
|
71
|
-
debug('web options %o', options);
|
|
72
|
-
debug('web manifestFiles %o', manifestFiles);
|
|
73
89
|
webPage = renderTemplate(
|
|
74
90
|
{
|
|
75
91
|
manifest: manifestFiles ?? defaultManifestFiles,
|
|
@@ -80,9 +96,10 @@ export default function renderHTML(config, manifest, manifestFiles, req, res) {
|
|
|
80
96
|
},
|
|
81
97
|
manifest
|
|
82
98
|
);
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
99
|
+
if (needHtmlCache) {
|
|
100
|
+
cache.set('template', webPage);
|
|
101
|
+
debug('set template cache');
|
|
102
|
+
}
|
|
86
103
|
} else {
|
|
87
104
|
debug('reuse template cache');
|
|
88
105
|
}
|
|
@@ -91,5 +108,5 @@ export default function renderHTML(config, manifest, manifestFiles, req, res) {
|
|
|
91
108
|
}
|
|
92
109
|
res.setHeader('Content-Type', HEADERS.TEXT_HTML);
|
|
93
110
|
res.send(webPage);
|
|
94
|
-
debug('
|
|
111
|
+
debug('web rendered');
|
|
95
112
|
}
|
package/src/utils/web-utils.ts
CHANGED
|
@@ -10,7 +10,7 @@ export type AuthorAvatar = Author & { avatar?: string };
|
|
|
10
10
|
const debug = buildDebug('verdaccio:web:utils');
|
|
11
11
|
|
|
12
12
|
export function validatePrimaryColor(primaryColor) {
|
|
13
|
-
const isHex =
|
|
13
|
+
const isHex = /^#([0-9A-F]{3}){1,2}$/i.test(primaryColor);
|
|
14
14
|
if (!isHex) {
|
|
15
15
|
debug('invalid primary color %o', primaryColor);
|
|
16
16
|
return;
|
package/test/api.readme.test.ts
CHANGED
|
@@ -38,7 +38,7 @@ describe('readme api', () => {
|
|
|
38
38
|
.expect(HEADER_TYPE.CONTENT_TYPE, HEADERS.TEXT_PLAIN_UTF8)
|
|
39
39
|
.expect(HTTP_STATUS.OK);
|
|
40
40
|
expect(response.text).toMatch('my readme scoped');
|
|
41
|
-
});
|
|
41
|
+
}, 70000);
|
|
42
42
|
|
|
43
43
|
test('should fetch readme scoped package with not found message', async () => {
|
|
44
44
|
const app = await initializeServer('default-test.yaml');
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
auth:
|
|
2
|
+
auth-memory:
|
|
3
|
+
users:
|
|
4
|
+
test:
|
|
5
|
+
name: test
|
|
6
|
+
password: test
|
|
7
|
+
|
|
8
|
+
web:
|
|
9
|
+
title: verdaccio web
|
|
10
|
+
login: true
|
|
11
|
+
scope: '@scope'
|
|
12
|
+
pkgManagers:
|
|
13
|
+
- pnpm
|
|
14
|
+
- yarn
|
|
15
|
+
showInfo: true
|
|
16
|
+
showSettings: true
|
|
17
|
+
showSearch: true
|
|
18
|
+
showFooter: true
|
|
19
|
+
showThemeSwitch: true
|
|
20
|
+
showDownloadTarball: true
|
|
21
|
+
showRaw: true
|
|
22
|
+
primary_color: '#ffffff'
|
|
23
|
+
logoURI: 'http://logo.org/logo.png'
|
|
24
|
+
flags:
|
|
25
|
+
- something: false
|
|
26
|
+
|
|
27
|
+
url_prefix: /prefix
|
|
28
|
+
|
|
29
|
+
publish:
|
|
30
|
+
allow_offline: false
|
|
31
|
+
|
|
32
|
+
uplinks:
|
|
33
|
+
|
|
34
|
+
log: { type: stdout, format: pretty, level: trace }
|
|
35
|
+
|
|
36
|
+
packages:
|
|
37
|
+
'@*/*':
|
|
38
|
+
access: $anonymous
|
|
39
|
+
publish: $anonymous
|
|
40
|
+
'**':
|
|
41
|
+
access: $anonymous
|
|
42
|
+
publish: $anonymous
|
|
43
|
+
_debug: true
|
|
44
|
+
|
|
45
|
+
flags:
|
|
46
|
+
changePassword: true
|
package/test/render.test.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { JSDOM } from 'jsdom';
|
|
1
2
|
import path from 'path';
|
|
2
3
|
import supertest from 'supertest';
|
|
3
4
|
|
|
@@ -28,34 +29,80 @@ describe('test web server', () => {
|
|
|
28
29
|
});
|
|
29
30
|
|
|
30
31
|
describe('render', () => {
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
32
|
+
describe('output', () => {
|
|
33
|
+
const render = async (config = 'default-test.yaml') => {
|
|
34
|
+
const response = await supertest(await initializeServer(config))
|
|
35
|
+
.get('/')
|
|
36
|
+
.set('Accept', HEADERS.TEXT_HTML)
|
|
37
|
+
.expect(HEADER_TYPE.CONTENT_TYPE, HEADERS.TEXT_HTML_UTF8)
|
|
38
|
+
.expect(HTTP_STATUS.OK);
|
|
39
|
+
return new JSDOM(response.text, { runScripts: 'dangerously' });
|
|
40
|
+
};
|
|
38
41
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
42
|
+
test('should match render set ui properties', async () => {
|
|
43
|
+
const {
|
|
44
|
+
window: { __VERDACCIO_BASENAME_UI_OPTIONS },
|
|
45
|
+
} = await render('web.yaml');
|
|
46
|
+
expect(__VERDACCIO_BASENAME_UI_OPTIONS).toEqual(
|
|
47
|
+
expect.objectContaining({
|
|
48
|
+
showInfo: true,
|
|
49
|
+
showSettings: true,
|
|
50
|
+
showThemeSwitch: true,
|
|
51
|
+
showFooter: true,
|
|
52
|
+
showSearch: true,
|
|
53
|
+
showDownloadTarball: true,
|
|
54
|
+
darkMode: false,
|
|
55
|
+
url_prefix: '/prefix',
|
|
56
|
+
basename: '/prefix/',
|
|
57
|
+
primaryColor: '#ffffff',
|
|
58
|
+
// FIXME: mock these values, avoid random
|
|
59
|
+
// base: 'http://127.0.0.1:60864/prefix/',
|
|
60
|
+
// version: '6.0.0-6-next.28',
|
|
61
|
+
logoURI: '',
|
|
62
|
+
flags: { searchRemote: true },
|
|
63
|
+
login: true,
|
|
64
|
+
pkgManagers: ['pnpm', 'yarn'],
|
|
65
|
+
title: 'verdaccio web',
|
|
66
|
+
scope: '@scope',
|
|
67
|
+
language: 'es-US',
|
|
68
|
+
})
|
|
69
|
+
);
|
|
70
|
+
});
|
|
46
71
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
.get('/-/static/not-found.js')
|
|
50
|
-
.set('Accept', HEADERS.TEXT_HTML)
|
|
51
|
-
.expect(HTTP_STATUS.NOT_FOUND);
|
|
72
|
+
test.todo('should default title');
|
|
73
|
+
test.todo('should need html cache');
|
|
52
74
|
});
|
|
53
75
|
|
|
54
|
-
|
|
55
|
-
return
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
76
|
+
describe('status', () => {
|
|
77
|
+
test('should return the http status 200 for root', async () => {
|
|
78
|
+
return supertest(await initializeServer('default-test.yaml'))
|
|
79
|
+
.get('/')
|
|
80
|
+
.set('Accept', HEADERS.TEXT_HTML)
|
|
81
|
+
.expect(HEADER_TYPE.CONTENT_TYPE, HEADERS.TEXT_HTML_UTF8)
|
|
82
|
+
.expect(HTTP_STATUS.OK);
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
test('should return the body for a package detail page', async () => {
|
|
86
|
+
return supertest(await initializeServer('default-test.yaml'))
|
|
87
|
+
.get('/-/web/section/some-package')
|
|
88
|
+
.set('Accept', HEADERS.TEXT_HTML)
|
|
89
|
+
.expect(HEADER_TYPE.CONTENT_TYPE, HEADERS.TEXT_HTML_UTF8)
|
|
90
|
+
.expect(HTTP_STATUS.OK);
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
test('should static file not found', async () => {
|
|
94
|
+
return supertest(await initializeServer('default-test.yaml'))
|
|
95
|
+
.get('/-/static/not-found.js')
|
|
96
|
+
.set('Accept', HEADERS.TEXT_HTML)
|
|
97
|
+
.expect(HTTP_STATUS.NOT_FOUND);
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
test('should static file found', async () => {
|
|
101
|
+
return supertest(await initializeServer('default-test.yaml'))
|
|
102
|
+
.get('/-/static/main.js')
|
|
103
|
+
.set('Accept', HEADERS.TEXT_HTML)
|
|
104
|
+
.expect(HTTP_STATUS.OK);
|
|
105
|
+
});
|
|
59
106
|
});
|
|
60
107
|
});
|
|
61
108
|
});
|
package/test/utils.spec.ts
CHANGED
|
@@ -1,13 +1,22 @@
|
|
|
1
1
|
import fs from 'fs';
|
|
2
2
|
import path from 'path';
|
|
3
3
|
|
|
4
|
-
import { parseReadme } from '../src/utils/web-utils';
|
|
4
|
+
import { parseReadme, validatePrimaryColor } from '../src/utils/web-utils';
|
|
5
5
|
|
|
6
6
|
const readmeFile = (fileName = 'markdown.md') => {
|
|
7
7
|
return fs.readFileSync(path.join(__dirname, `./partials/readme/${fileName}`));
|
|
8
8
|
};
|
|
9
9
|
|
|
10
10
|
describe('Utilities', () => {
|
|
11
|
+
describe('validatePrimaryColor', () => {
|
|
12
|
+
test('is valid', () => {
|
|
13
|
+
expect(validatePrimaryColor('#222222')).toEqual('#222222');
|
|
14
|
+
expect(validatePrimaryColor('#222fff')).toEqual('#222fff');
|
|
15
|
+
});
|
|
16
|
+
test('is invalid', () => {
|
|
17
|
+
expect(validatePrimaryColor('fff')).toBeUndefined();
|
|
18
|
+
});
|
|
19
|
+
});
|
|
11
20
|
describe('parseReadme', () => {
|
|
12
21
|
test('should parse makrdown text to html template', () => {
|
|
13
22
|
const markdown = '# markdown';
|