Refactor testing harness to use defaults (#808)

* Refactor testing harness to use defaults

- Move tests into defaultly named test folders
- Use default test suffix of ".test" instead of "_test"
- Make cluster-store tests unit tests by adding more
    nesting, so that order of tests doesn't matter

Signed-off-by: Sebastian Malton <sebastian@malton.name>

Co-authored-by: Sebastian Malton <smalton@mirantis.com>
This commit is contained in:
Sebastian MaltonandSebastian Malton authored and GitHub committed 2020-10-02 10:05:59 -04:00
1 parent 14d3d88278
commit 87061cee9e
25 files changed
+345 -307

No files matched your search

@@ -1,11 +1,11 @@
import { IKubeApiParsed, parseKubeApi } from "./kube-api-parse";
import { IKubeApiParsed, parseKubeApi } from "../kube-api-parse";
interface KubeApi_Parse_Test {
interface KubeApiParseTestData {
url: string;
expected: Required<IKubeApiParsed>;
}
const tests: KubeApi_Parse_Test[] = [
const tests: KubeApiParseTestData[] = [
{
url: "/apis/apiextensions.k8s.io/v1beta1/customresourcedefinitions/prometheuses.monitoring.coreos.com",
expected: {
@@ -125,11 +125,10 @@ const tests: KubeApi_Parse_Test[] = [
},
];
describe.only("parseApi unit tests", () => {
for (const i in tests) {
const { url: tUrl, expected:tExpect} = tests[i];
test(`test #${parseInt(i)+1}`, () => {
expect(parseKubeApi(tUrl)).toStrictEqual(tExpect);
describe("parseApi unit tests", () => {
for (const { url, expected } of tests) {
test(`testing "${url}"`, () => {
expect(parseKubeApi(url)).toStrictEqual(expected);
});
}
});
@@ -4,7 +4,7 @@ import { Input } from "../../input";
import { observable, autorun } from "mobx";
import { observer, disposeOnUnmount } from "mobx-react";
import { SubTitle } from "../../layout/sub-title";
import { isRequired } from "../../input/input.validators";
import { isRequired } from "../../input/input_validators";
interface Props {
cluster: Cluster;
@@ -33,7 +33,7 @@ export class ClusterNameSetting extends React.Component<Props> {
render() {
return (
<>
<SubTitle title="Cluster Name"/>
<SubTitle title="Cluster Name" />
<p>Define cluster name.</p>
<Input
theme="round-black"
@@ -3,7 +3,7 @@ import { observable, autorun } from "mobx";
import { observer, disposeOnUnmount } from "mobx-react";
import { Cluster } from "../../../../main/cluster";
import { Input } from "../../input";
import { isUrl } from "../../input/input.validators";
import { isUrl } from "../../input/input_validators";
import { SubTitle } from "../../layout/sub-title";
interface Props {
@@ -33,7 +33,7 @@ export class ClusterProxySetting extends React.Component<Props> {
render() {
return (
<>
<SubTitle title="HTTP Proxy"/>
<SubTitle title="HTTP Proxy" />
<p>HTTP Proxy server. Used for communicating with Kubernetes API.</p>
<Input
theme="round-black"
@@ -8,7 +8,7 @@ import { _i18n } from "../../i18n";
import { Dialog, DialogProps } from "../dialog";
import { Wizard, WizardStep } from "../wizard";
import { Input } from "../input";
import { systemName } from "../input/input.validators";
import { systemName } from "../input/input_validators";
import { IResourceQuotaValues, resourceQuotaApi } from "../../api/endpoints/resource-quota.api";
import { Select } from "../select";
import { Icon } from "../icon";
@@ -73,7 +73,7 @@ export class AddQuotaDialog extends React.Component<Props> {
const isCount = quota.startsWith("count/");
const icon = isCompute ? "memory" : isStorage ? "storage" : isCount ? "looks_one" : "";
return {
label: icon ? <span className="nobr"><Icon material={icon}/> {quota}</span> : quota,
label: icon ? <span className="nobr"><Icon material={icon} /> {quota}</span> : quota,
value: quota,
};
});
@@ -151,7 +151,7 @@ export class AddQuotaDialog extends React.Component<Props> {
/>
</div>
<SubTitle title={<Trans>Namespace</Trans>}/>
<SubTitle title={<Trans>Namespace</Trans>} />
<NamespaceSelect
value={this.namespace}
placeholder={_i18n._(t`Namespace`)}
@@ -160,7 +160,7 @@ export class AddQuotaDialog extends React.Component<Props> {
onChange={({ value }) => this.namespace = value}
/>
<SubTitle title={<Trans>Values</Trans>}/>
<SubTitle title={<Trans>Values</Trans>} />
<div className="flex gaps align-center">
<Select
className="quota-select"
@@ -191,7 +191,7 @@ export class AddQuotaDialog extends React.Component<Props> {
<div key={quota} className="quota flex gaps inline align-center">
<div className="name">{quota}</div>
<div className="value">{value}</div>
<Icon material="clear" onClick={() => this.quotas[quota] = ""}/>
<Icon material="clear" onClick={() => this.quotas[quota] = ""} />
</div>
)
})}
@@ -8,7 +8,7 @@ import { _i18n } from "../../i18n";
import { Dialog, DialogProps } from "../dialog";
import { Wizard, WizardStep } from "../wizard";
import { Input } from "../input";
import { systemName } from "../input/input.validators";
import { systemName } from "../input/input_validators";
import { Secret, secretsApi, SecretType } from "../../api/endpoints";
import { SubTitle } from "../layout/sub-title";
import { NamespaceSelect } from "../+namespaces/namespace-select";
@@ -184,7 +184,7 @@ export class AddSecretDialog extends React.Component<Props> {
<Wizard header={header} done={this.close}>
<WizardStep contentClass="flow column" nextLabel={<Trans>Create</Trans>} next={this.createSecret}>
<div className="secret-name">
<SubTitle title={<Trans>Secret name</Trans>}/>
<SubTitle title={<Trans>Secret name</Trans>} />
<Input
autoFocus required
placeholder={_i18n._(t`Name`)}
@@ -194,7 +194,7 @@ export class AddSecretDialog extends React.Component<Props> {
</div>
<div className="flex auto gaps">
<div className="secret-namespace">
<SubTitle title={<Trans>Namespace</Trans>}/>
<SubTitle title={<Trans>Namespace</Trans>} />
<NamespaceSelect
themeName="light"
value={namespace}
@@ -202,7 +202,7 @@ export class AddSecretDialog extends React.Component<Props> {
/>
</div>
<div className="secret-type">
<SubTitle title={<Trans>Secret type</Trans>}/>
<SubTitle title={<Trans>Secret type</Trans>} />
<Select
themeName="light"
options={this.types}
@@ -10,7 +10,7 @@ import { Wizard, WizardStep } from "../wizard";
import { namespaceStore } from "./namespace.store";
import { Namespace } from "../../api/endpoints";
import { Input } from "../input";
import { systemName } from "../input/input.validators";
import { systemName } from "../input/input_validators";
import { Notifications } from "../notifications";
interface Props extends DialogProps {
@@ -1,6 +1,6 @@
import React, { useState } from 'react';
import { Trans } from '@lingui/macro';
import { isPath } from '../input/input.validators';
import { isPath } from '../input/input_validators';
import { Checkbox } from '../checkbox';
import { Input } from '../input';
import { SubTitle } from '../layout/sub-title';
@@ -10,7 +10,7 @@ import { Wizard, WizardStep } from "../wizard";
import { SubTitle } from "../layout/sub-title";
import { serviceAccountsStore } from "./service-accounts.store";
import { Input } from "../input";
import { systemName } from "../input/input.validators";
import { systemName } from "../input/input_validators";
import { NamespaceSelect } from "../+namespaces/namespace-select";
import { Notifications } from "../notifications";
import { showDetails } from "../../navigation";
@@ -62,14 +62,14 @@ export class CreateServiceAccountDialog extends React.Component<Props> {
>
<Wizard header={header} done={this.close}>
<WizardStep nextLabel={<Trans>Create</Trans>} next={this.createAccount}>
<SubTitle title={<Trans>Account Name</Trans>}/>
<SubTitle title={<Trans>Account Name</Trans>} />
<Input
autoFocus required
placeholder={_i18n._(t`Enter a name`)}
validators={systemName}
value={name} onChange={v => this.name = v.toLowerCase()}
/>
<SubTitle title={<Trans>Namespace</Trans>}/>
<SubTitle title={<Trans>Namespace</Trans>} />
<NamespaceSelect
themeName="light"
value={namespace}
@@ -10,7 +10,7 @@ import { CronJob, cronJobApi, jobApi, Job } from "../../api/endpoints";
import { Notifications } from "../notifications";
import { cssNames } from "../../utils";
import { Input } from "../input";
import { systemName, maxLength } from "../input/input.validators";
import { systemName, maxLength } from "../input/input_validators";
interface Props extends Partial<DialogProps> {
}
@@ -12,7 +12,7 @@ import { Icon } from "../icon";
import { Input } from "../input";
import { cssNames, prevDefault } from "../../utils";
import { Button } from "../button";
import { isRequired, Validator } from "../input/input.validators";
import { isRequired, Validator } from "../input/input_validators";
@observer
export class Workspaces extends React.Component {
@@ -1,4 +1,4 @@
import { isEmail, systemName } from "./input.validators";
import { isEmail, systemName } from "../input_validators";
describe("input validation tests", () => {
describe("isEmail tests", () => {
+4 -4
View File
@@ -3,7 +3,7 @@ import "./input.scss";
import React, { DOMAttributes, InputHTMLAttributes, TextareaHTMLAttributes } from "react";
import { autobind, cssNames, debouncePromise } from "../../utils";
import { Icon } from "../icon";
import { conditionalValidators, Validator } from "./input.validators";
import { conditionalValidators, Validator } from "./input_validators";
import isString from "lodash/isString"
import isFunction from "lodash/isFunction"
import isBoolean from "lodash/isBoolean"
@@ -288,9 +288,9 @@ export class Input extends React.Component<InputProps, State> {
return (
<div className={className}>
<label className="input-area flex gaps align-center">
{isString(iconLeft) ? <Icon material={iconLeft}/> : iconLeft}
{multiLine ? <textarea {...inputProps as any}/> : <input {...inputProps as any}/>}
{isString(iconRight) ? <Icon material={iconRight}/> : iconRight}
{isString(iconLeft) ? <Icon material={iconLeft} /> : iconLeft}
{multiLine ? <textarea {...inputProps as any} /> : <input {...inputProps as any} />}
{isString(iconRight) ? <Icon material={iconRight} /> : iconRight}
</label>
<div className="input-info flex gaps">
{!valid && dirty && (
@@ -1,4 +1,4 @@
import { formatDuration } from "./formatDuration";
import { formatDuration } from "../formatDuration";
const second = 1000;
const minute = 60 * second;
@@ -9,34 +9,34 @@ const week = 7 * day;
describe("human format durations", () => {
test("long formatted durations less than 24 hours long shouldn't have a 'd' component", () => {
const res = formatDuration(19 * 60 * 60 * 1000, false);
expect(res).not.toContain("d");
expect(res).toBe("19h");
});
test("long formatted durations more than a week have correct day count", () => {
const res = formatDuration(2 * week + 2 * day, false);
expect(res).toBe("2w 2d");
});
test("durations > 1/2 week shouldn't show 1w has passed", () => {
const res = formatDuration(5 * 24 * 60 * 60 * 1000, false);
expect(res).not.toContain("w");
expect(res).toBe("5d");
});
test("durations shouldn't include zero magnitude parts", () => {
const res = formatDuration(6 * day + 2 * minute, false);
expect(res).not.toContain("h");
expect(res).toBe("6d 2m");
});
test("seconds are ignored unless they are significant (< 1m)", () => {
const insignificant = formatDuration(1 * hour + 2 * minute + 31 * second, false);
expect(insignificant).not.toContain("s");
expect(insignificant).toBe("1h 2m");
@@ -1,4 +1,4 @@
import { metricUnitsToNumber } from "./metricUnitsToNumber";
import { metricUnitsToNumber } from "../metricUnitsToNumber";
describe("metricUnitsToNumber tests", () => {
test("plain number", () => {