Skip to content

Commit

Permalink
Some code cleanup, add jest coverage and begin using it for utility f…
Browse files Browse the repository at this point in the history
…unctions
  • Loading branch information
DaneEveritt committed Jun 26, 2022
1 parent ca39830 commit 1eb3ea2
Show file tree
Hide file tree
Showing 29 changed files with 2,044 additions and 134 deletions.
1 change: 1 addition & 0 deletions .eslintrc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ extends:
- "standard"
- "plugin:react/recommended"
- "plugin:@typescript-eslint/recommended"
- "plugin:jest-dom/recommended"
rules:
quotes:
- warn
Expand Down
35 changes: 23 additions & 12 deletions babel.config.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,6 @@
module.exports = {
presets: [
'@babel/typescript',
['@babel/env', {
modules: false,
useBuiltIns: 'entry',
corejs: 3,
}],
'@babel/react',
],
plugins: [
module.exports = function (api) {
let targets = {};
const plugins = [
'babel-plugin-macros',
'styled-components',
'react-hot-loader/babel',
Expand All @@ -19,5 +11,24 @@ module.exports = {
'@babel/proposal-optional-chaining',
'@babel/proposal-nullish-coalescing-operator',
'@babel/syntax-dynamic-import',
],
];

if (api.env('test')) {
targets = { node: 'current' };
plugins.push('@babel/transform-modules-commonjs');
}

return {
plugins,
presets: [
'@babel/typescript',
['@babel/env', {
modules: false,
useBuiltIns: 'entry',
corejs: 3,
targets,
}],
'@babel/react',
]
};
};
28 changes: 28 additions & 0 deletions jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
const { pathsToModuleNameMapper } = require('ts-jest');
const { compilerOptions } = require('./tsconfig');

/** @type {import('ts-jest').InitialOptionsTsJest} */
module.exports = {
preset: 'ts-jest',
globals: {
'ts-jest': {
isolatedModules: true,
},
},
moduleFileExtensions: ['js', 'ts', 'tsx', 'd.ts', 'json', 'node'],
moduleNameMapper: {
'\\.(jpe?g|png|gif|svg)$': '<rootDir>/resources/scripts/__mocks__/file.ts',
'\\.(s?css|less)$': 'identity-obj-proxy',
...pathsToModuleNameMapper(compilerOptions.paths, {
prefix: '<rootDir>/',
}),
},
setupFilesAfterEnv: [
'<rootDir>/resources/scripts/setup-tests.ts',
],
transform: {
'.*\\.[t|j]sx$': 'babel-jest',
'.*\\.ts$': 'ts-jest',
},
testPathIgnorePatterns: ['/node_modules/'],
};
12 changes: 12 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -60,16 +60,22 @@
"@babel/plugin-proposal-object-rest-spread": "^7.12.1",
"@babel/plugin-proposal-optional-chaining": "^7.12.1",
"@babel/plugin-syntax-dynamic-import": "^7.8.3",
"@babel/plugin-transform-modules-commonjs": "^7.18.2",
"@babel/plugin-transform-react-jsx": "^7.12.1",
"@babel/plugin-transform-runtime": "^7.12.1",
"@babel/preset-env": "^7.12.1",
"@babel/preset-react": "^7.12.1",
"@babel/preset-typescript": "^7.12.1",
"@babel/runtime": "^7.12.1",
"@testing-library/dom": "^8.14.0",
"@testing-library/jest-dom": "^5.16.4",
"@testing-library/react": "12.1.5",
"@testing-library/user-event": "^14.2.1",
"@types/chart.js": "^2.8.5",
"@types/codemirror": "^0.0.98",
"@types/debounce": "^1.2.0",
"@types/events": "^3.0.0",
"@types/jest": "^28.1.3",
"@types/node": "^14.11.10",
"@types/qrcode.react": "^1.0.1",
"@types/query-string": "^6.3.0",
Expand All @@ -88,18 +94,22 @@
"@typescript-eslint/eslint-plugin": "^4.25.0",
"@typescript-eslint/parser": "^4.25.0",
"autoprefixer": "^10.4.7",
"babel-jest": "^28.1.1",
"babel-loader": "^8.2.5",
"babel-plugin-styled-components": "^2.0.7",
"cross-env": "^7.0.2",
"css-loader": "^5.2.7",
"eslint": "^7.27.0",
"eslint-config-standard": "^16.0.3",
"eslint-plugin-import": "^2.23.3",
"eslint-plugin-jest-dom": "^4.0.2",
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-promise": "^5.1.0",
"eslint-plugin-react": "^7.23.2",
"eslint-plugin-react-hooks": "^4.2.0",
"fork-ts-checker-webpack-plugin": "^6.2.10",
"identity-obj-proxy": "^3.0.0",
"jest": "^28.1.1",
"postcss": "^8.4.14",
"postcss-import": "^14.1.0",
"postcss-loader": "^4.0.0",
Expand All @@ -111,6 +121,7 @@
"svg-url-loader": "^7.1.1",
"terser-webpack-plugin": "^4.2.3",
"ts-essentials": "^9.1.2",
"ts-jest": "^28.0.5",
"twin.macro": "^2.8.2",
"typescript": "^4.7.3",
"webpack": "^4.43.0",
Expand All @@ -122,6 +133,7 @@
},
"scripts": {
"clean": "cd public/assets && find . \\( -name \"*.js\" -o -name \"*.map\" \\) -type f -delete",
"test": "jest",
"lint": "eslint ./resources/scripts/**/*.{ts,tsx} --ext .ts,.tsx",
"watch": "cross-env NODE_ENV=development ./node_modules/.bin/webpack --watch --progress",
"build": "cross-env NODE_ENV=development ./node_modules/.bin/webpack --progress",
Expand Down
1 change: 1 addition & 0 deletions resources/scripts/__mocks__/file.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
module.exports = 'test-file-stub';
12 changes: 6 additions & 6 deletions resources/scripts/components/dashboard/ServerRow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { faEthernet, faHdd, faMemory, faMicrochip, faServer } from '@fortawesome
import { Link } from 'react-router-dom';
import { Server } from '@/api/server/getServer';
import getServerResourceUsage, { ServerPowerState, ServerStats } from '@/api/server/getServerResourceUsage';
import { bytesToHuman, formatIp, megabytesToHuman } from '@/helpers';
import { bytesToString, ip, mbToBytes } from '@/lib/formatters';
import tw from 'twin.macro';
import GreyRowBox from '@/components/elements/GreyRowBox';
import Spinner from '@/components/elements/Spinner';
Expand Down Expand Up @@ -74,8 +74,8 @@ export default ({ server, className }: { server: Server; className?: string }) =
alarms.disk = server.limits.disk === 0 ? false : isAlarmState(stats.diskUsageInBytes, server.limits.disk);
}

const diskLimit = server.limits.disk !== 0 ? megabytesToHuman(server.limits.disk) : 'Unlimited';
const memoryLimit = server.limits.memory !== 0 ? megabytesToHuman(server.limits.memory) : 'Unlimited';
const diskLimit = server.limits.disk !== 0 ? bytesToString(mbToBytes(server.limits.disk)) : 'Unlimited';
const memoryLimit = server.limits.memory !== 0 ? bytesToString(mbToBytes(server.limits.memory)) : 'Unlimited';
const cpuLimit = server.limits.cpu !== 0 ? server.limits.cpu + ' %' : 'Unlimited';

return (
Expand All @@ -98,7 +98,7 @@ export default ({ server, className }: { server: Server; className?: string }) =
{
server.allocations.filter(alloc => alloc.isDefault).map(allocation => (
<React.Fragment key={allocation.ip + allocation.port.toString()}>
{allocation.alias || formatIp(allocation.ip)}:{allocation.port}
{allocation.alias || ip(allocation.ip)}:{allocation.port}
</React.Fragment>
))
}
Expand Down Expand Up @@ -146,7 +146,7 @@ export default ({ server, className }: { server: Server; className?: string }) =
<div css={tw`flex justify-center`}>
<Icon icon={faMemory} $alarm={alarms.memory}/>
<IconDescription $alarm={alarms.memory}>
{bytesToHuman(stats.memoryUsageInBytes)}
{bytesToString(stats.memoryUsageInBytes)}
</IconDescription>
</div>
<p css={tw`text-xs text-neutral-600 text-center mt-1`}>of {memoryLimit}</p>
Expand All @@ -155,7 +155,7 @@ export default ({ server, className }: { server: Server; className?: string }) =
<div css={tw`flex justify-center`}>
<Icon icon={faHdd} $alarm={alarms.disk}/>
<IconDescription $alarm={alarms.disk}>
{bytesToHuman(stats.diskUsageInBytes)}
{bytesToString(stats.diskUsageInBytes)}
</IconDescription>
</div>
<p css={tw`text-xs text-neutral-600 text-center mt-1`}>of {diskLimit}</p>
Expand Down
5 changes: 3 additions & 2 deletions resources/scripts/components/dashboard/search/SearchModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ import { Link } from 'react-router-dom';
import styled from 'styled-components/macro';
import tw from 'twin.macro';
import Input from '@/components/elements/Input';
import { formatIp } from '@/helpers';
import { ip } from '@/lib/formatters';

type Props = RequiredModalProps;

interface Values {
Expand Down Expand Up @@ -109,7 +110,7 @@ export default ({ ...props }: Props) => {
<p css={tw`mt-1 text-xs text-neutral-400`}>
{
server.allocations.filter(alloc => alloc.isDefault).map(allocation => (
<span key={allocation.ip + allocation.port.toString()}>{allocation.alias || formatIp(allocation.ip)}:{allocation.port}</span>
<span key={allocation.ip + allocation.port.toString()}>{allocation.alias || ip(allocation.ip)}:{allocation.port}</span>
))
}
</p>
Expand Down
2 changes: 1 addition & 1 deletion resources/scripts/components/elements/InputError.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React from 'react';
import { FormikErrors, FormikTouched } from 'formik';
import tw from 'twin.macro';
import { capitalize } from '@/helpers';
import { capitalize } from '@/lib/strings';

interface Props {
errors: FormikErrors<any>;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import ActivityLogMetaButton from '@/components/elements/activity/ActivityLogMet
import { TerminalIcon } from '@heroicons/react/solid';
import classNames from 'classnames';
import style from './style.module.css';
import { isObject } from '@/helpers';
import { isObject } from '@/lib/objects';
import Avatar from '@/components/Avatar';
import useLocationHash from '@/plugins/useLocationHash';

Expand Down
4 changes: 2 additions & 2 deletions resources/scripts/components/server/backups/BackupRow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { faArchive, faEllipsisH, faLock } from '@fortawesome/free-solid-svg-icons';
import { format, formatDistanceToNow } from 'date-fns';
import Spinner from '@/components/elements/Spinner';
import { bytesToHuman } from '@/helpers';
import { bytesToString } from '@/lib/formatters';
import Can from '@/components/elements/Can';
import useWebsocketEvent from '@/plugins/useWebsocketEvent';
import BackupContextMenu from '@/components/server/backups/BackupContextMenu';
Expand Down Expand Up @@ -64,7 +64,7 @@ export default ({ backup, className }: Props) => {
{backup.name}
</p>
{(backup.completedAt !== null && backup.isSuccessful) &&
<span css={tw`ml-3 text-neutral-300 text-xs font-extralight hidden sm:inline`}>{bytesToHuman(backup.bytes)}</span>
<span css={tw`ml-3 text-neutral-300 text-xs font-extralight hidden sm:inline`}>{bytesToString(backup.bytes)}</span>
}
</div>
<p css={tw`mt-1 md:mt-0 text-xs text-neutral-400 font-mono truncate`}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {
faMicrochip,
faWifi,
} from '@fortawesome/free-solid-svg-icons';
import { bytesToHuman, formatIp, megabytesToHuman } from '@/helpers';
import { bytesToString, ip, mbToBytes } from '@/lib/formatters';
import { ServerContext } from '@/state/server';
import { SocketEvent, SocketRequest } from '@/components/server/events';
import UptimeDuration from '@/components/server/UptimeDuration';
Expand Down Expand Up @@ -41,7 +41,7 @@ const ServerDetailsBlock = ({ className }: { className?: string }) => {
const allocation = ServerContext.useStoreState(state => {
const match = state.server.data!.allocations.find(allocation => allocation.isDefault);

return !match ? 'n/a' : `${match.alias || formatIp(match.ip)}:${match.port}`;
return !match ? 'n/a' : `${match.alias || ip(match.ip)}:${match.port}`;
});

useEffect(() => {
Expand Down Expand Up @@ -106,26 +106,26 @@ const ServerDetailsBlock = ({ className }: { className?: string }) => {
title={'Memory'}
color={getBackgroundColor(stats.memory / 1024, limits.memory * 1024)}
description={limits.memory
? `This server is allowed to use up to ${megabytesToHuman(limits.memory)} of memory.`
? `This server is allowed to use up to ${bytesToString(mbToBytes(limits.memory))} of memory.`
: 'No memory limit has been configured for this server.'
}
>
{status === 'offline' ?
<span className={'text-gray-400'}>Offline</span>
:
bytesToHuman(stats.memory)
bytesToString(stats.memory)
}
</StatBlock>
<StatBlock
icon={faHdd}
title={'Disk'}
color={getBackgroundColor(stats.disk / 1024, limits.disk * 1024)}
description={limits.disk
? `This server is allowed to use up to ${megabytesToHuman(limits.disk)} of disk space.`
? `This server is allowed to use up to ${bytesToString(mbToBytes(limits.disk))} of disk space.`
: 'No disk space limit has been configured for this server.'
}
>
{bytesToHuman(stats.disk)}
{bytesToString(stats.disk)}
</StatBlock>
<StatBlock
icon={faCloudDownloadAlt}
Expand All @@ -135,7 +135,7 @@ const ServerDetailsBlock = ({ className }: { className?: string }) => {
{status === 'offline' ?
<span className={'text-gray-400'}>Offline</span>
:
bytesToHuman(stats.tx)
bytesToString(stats.tx)
}
</StatBlock>
<StatBlock
Expand All @@ -146,7 +146,7 @@ const ServerDetailsBlock = ({ className }: { className?: string }) => {
{status === 'offline' ?
<span className={'text-gray-400'}>Offline</span>
:
bytesToHuman(stats.rx)
bytesToString(stats.rx)
}
</StatBlock>
</div>
Expand Down
7 changes: 4 additions & 3 deletions resources/scripts/components/server/console/StatGraphs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ import { SocketEvent } from '@/components/server/events';
import useWebsocketEvent from '@/plugins/useWebsocketEvent';
import { Line } from 'react-chartjs-2';
import { useChart, useChartTickLabel } from '@/components/server/console/chart';
import { bytesToHuman, toRGBA } from '@/helpers';
import { hexToRgba } from '@/lib/helpers';
import { bytesToString } from '@/lib/formatters';
import { CloudDownloadIcon, CloudUploadIcon } from '@heroicons/react/solid';
import { theme } from 'twin.macro';
import ChartBlock from '@/components/server/console/ChartBlock';
Expand All @@ -24,7 +25,7 @@ export default () => {
y: {
ticks: {
callback (value) {
return bytesToHuman(typeof value === 'string' ? parseInt(value, 10) : value);
return bytesToString(typeof value === 'string' ? parseInt(value, 10) : value);
},
},
},
Expand All @@ -35,7 +36,7 @@ export default () => {
...opts,
label: !index ? 'Network In' : 'Network Out',
borderColor: !index ? theme('colors.cyan.400') : theme('colors.yellow.400'),
backgroundColor: toRGBA(!index ? theme('colors.cyan.700') : theme('colors.yellow.700'), 0.5),
backgroundColor: hexToRgba(!index ? theme('colors.cyan.700') : theme('colors.yellow.700'), 0.5),
};
},
});
Expand Down
4 changes: 2 additions & 2 deletions resources/scripts/components/server/console/chart.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { DeepPartial } from 'ts-essentials';
import { useState } from 'react';
import { deepmerge, deepmergeCustom } from 'deepmerge-ts';
import { theme } from 'twin.macro';
import { toRGBA } from '@/helpers';
import { hexToRgba } from '@/lib/helpers';

ChartJS.register(LineElement, PointElement, Filler, LinearScale);

Expand Down Expand Up @@ -86,7 +86,7 @@ function getEmptyData (label: string, sets = 1, callback?: ChartDatasetCallback
label,
data: Array(20).fill(0),
borderColor: theme('colors.cyan.400'),
backgroundColor: toRGBA(theme('colors.cyan.700'), 0.5),
backgroundColor: hexToRgba(theme('colors.cyan.700'), 0.5),
}, index)),
};
}
Expand Down
2 changes: 1 addition & 1 deletion resources/scripts/components/server/features/Features.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React, { useMemo } from 'react';
import features from './index';
import { getObjectKeys } from '@/helpers';
import { getObjectKeys } from '@/lib/objects';

type ListItems = [ string, React.ComponentType ][];

Expand Down
5 changes: 3 additions & 2 deletions resources/scripts/components/server/files/FileObjectRow.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { faFileAlt, faFileArchive, faFileImport, faFolder } from '@fortawesome/free-solid-svg-icons';
import { bytesToHuman, encodePathSegments } from '@/helpers';
import { encodePathSegments } from '@/helpers';
import { differenceInHours, format, formatDistanceToNow } from 'date-fns';
import React, { memo } from 'react';
import { FileObject } from '@/api/server/files/loadDirectory';
Expand All @@ -13,6 +13,7 @@ import styled from 'styled-components/macro';
import SelectFileCheckbox from '@/components/server/files/SelectFileCheckbox';
import { usePermissions } from '@/plugins/usePermissions';
import { join } from 'path';
import { bytesToString } from '@/lib/formatters';

const Row = styled.div`
${tw`flex bg-neutral-700 rounded-sm mb-px text-sm hover:text-neutral-100 cursor-pointer items-center no-underline hover:bg-neutral-600`};
Expand Down Expand Up @@ -61,7 +62,7 @@ const FileObjectRow = ({ file }: { file: FileObject }) => (
</div>
{file.isFile &&
<div css={tw`w-1/6 text-right mr-4 hidden sm:block`}>
{bytesToHuman(file.size)}
{bytesToString(file.size)}
</div>
}
<div
Expand Down
Loading

0 comments on commit 1eb3ea2

Please sign in to comment.