浏览代码

Refactor new component tests

Azat Belgibayev 3 年之前
父节点
当前提交
60403c5d4a

+ 55 - 15
kafka-ui-react-app/src/components/Topics/New/__tests__/New.spec.tsx

@@ -1,29 +1,69 @@
 import React from 'react';
-import { mount } from 'enzyme';
 import New from 'components/Topics/New/New';
-import { StaticRouter } from 'react-router';
-import { clusterTopicNewPath } from 'lib/paths';
+import { Router } from 'react-router';
 import configureStore from 'redux-mock-store';
 import { RootState } from 'redux/interfaces';
 import { Provider } from 'react-redux';
+import { fireEvent, render, screen, waitFor } from '@testing-library/react';
+import { createMemoryHistory } from 'history';
+import fetchMock from 'fetch-mock-jest';
+import { clusterTopicNewPath, clusterTopicPath } from 'lib/paths';
 
 const mockStore = configureStore();
 
 describe('New', () => {
   const clusterName = 'local';
+  const topicName = 'test-topic';
 
   const initialState: Partial<RootState> = {};
-  const store = mockStore(initialState);
-
-  it('matches snapshot', () => {
-    expect(
-      mount(
-        <StaticRouter location={{ pathname: clusterTopicNewPath(clusterName) }}>
-          <Provider store={store}>
-            <New />
-          </Provider>
-        </StaticRouter>
-      )
-    ).toMatchSnapshot();
+  const storeMock = mockStore(initialState);
+  const historyMock = createMemoryHistory();
+
+  beforeEach(() => {
+    fetchMock.restore();
+  });
+
+  const setupComponent = (history = historyMock, store = storeMock) => (
+    <Router history={history}>
+      <Provider store={store}>
+        <New />
+      </Provider>
+    </Router>
+  );
+
+  it('validates form', async () => {
+    const mockedHistory = createMemoryHistory();
+    jest.spyOn(mockedHistory, 'push');
+
+    render(setupComponent(mockedHistory));
+
+    await waitFor(async () => {
+      fireEvent.click(await screen.findByText('Send'));
+      const errorText = await screen.findByText('Topic Name is required.');
+      expect(mockedHistory.push).toBeCalledTimes(0);
+      expect(errorText).toBeTruthy();
+    });
+  });
+
+  it('submits valid form', async () => {
+    const mockedHistory = createMemoryHistory({
+      initialEntries: [clusterTopicNewPath(clusterName)],
+    });
+    jest.spyOn(mockedHistory, 'push');
+
+    render(setupComponent());
+
+    const input = await screen.findByPlaceholderText('Topic Name');
+    fireEvent.change(input, { target: { value: topicName } });
+    expect(input).toHaveValue(topicName);
+
+    waitFor(async () => {
+      fireEvent.click(await screen.findByText('Send'));
+
+      expect(mockedHistory.location.pathname).toBe(
+        clusterTopicPath(clusterName, topicName)
+      );
+      expect(mockedHistory.push).toBeCalledTimes(1);
+    });
   });
 });

+ 0 - 877
kafka-ui-react-app/src/components/Topics/New/__tests__/__snapshots__/New.spec.tsx.snap

@@ -1,877 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`New matches snapshot 1`] = `
-<StaticRouter
-  location={
-    Object {
-      "pathname": "/ui/clusters/local/topics/create_new",
-    }
-  }
->
-  <Router
-    history={
-      Object {
-        "action": "POP",
-        "block": [Function],
-        "createHref": [Function],
-        "go": [Function],
-        "goBack": [Function],
-        "goForward": [Function],
-        "listen": [Function],
-        "location": Object {
-          "hash": "",
-          "pathname": "/ui/clusters/local/topics/create_new",
-          "search": "",
-        },
-        "push": [Function],
-        "replace": [Function],
-      }
-    }
-    staticContext={Object {}}
-  >
-    <Provider
-      store={
-        Object {
-          "clearActions": [Function],
-          "dispatch": [Function],
-          "getActions": [Function],
-          "getState": [Function],
-          "replaceReducer": [Function],
-          "subscribe": [Function],
-        }
-      }
-    >
-      <New>
-        <div
-          className="section"
-        >
-          <div
-            className="level"
-          >
-            <div
-              className="level-item level-left"
-            >
-              <Breadcrumb
-                links={
-                  Array [
-                    Object {
-                      "href": "/ui/clusters/undefined/topics",
-                      "label": "All Topics",
-                    },
-                  ]
-                }
-              >
-                <nav
-                  aria-label="breadcrumbs"
-                  className="breadcrumb"
-                >
-                  <ul>
-                    <li
-                      key="/ui/clusters/undefined/topics"
-                    >
-                      <Link
-                        to="/ui/clusters/undefined/topics"
-                      >
-                        <LinkAnchor
-                          href="/ui/clusters/undefined/topics"
-                          navigate={[Function]}
-                        >
-                          <a
-                            href="/ui/clusters/undefined/topics"
-                            onClick={[Function]}
-                          >
-                            All Topics
-                          </a>
-                        </LinkAnchor>
-                      </Link>
-                    </li>
-                    <li
-                      className="is-active"
-                    >
-                      <span
-                        className=""
-                      >
-                        New Topic
-                      </span>
-                    </li>
-                  </ul>
-                </nav>
-              </Breadcrumb>
-            </div>
-          </div>
-          <div
-            className="box"
-          >
-            <Component
-              clearErrors={[Function]}
-              control={
-                Object {
-                  "controllerSubjectRef": Object {
-                    "current": Re {
-                      "observers": Array [],
-                    },
-                  },
-                  "defaultValuesRef": Object {
-                    "current": Object {},
-                  },
-                  "fieldArrayDefaultValuesRef": Object {
-                    "current": Object {
-                      "customParams": Array [],
-                    },
-                  },
-                  "fieldArrayNamesRef": Object {
-                    "current": Set {
-                      "customParams",
-                    },
-                  },
-                  "fieldArraySubjectRef": Object {
-                    "current": Re {
-                      "observers": Array [
-                        ke {
-                          "closed": false,
-                          "observer": Object {
-                            "next": [Function],
-                          },
-                        },
-                        ke {
-                          "closed": false,
-                          "observer": Object {
-                            "next": [Function],
-                          },
-                        },
-                      ],
-                    },
-                  },
-                  "fieldsRef": Object {
-                    "current": Object {
-                      "cleanupPolicy": Object {
-                        "_f": Object {
-                          "mount": true,
-                          "name": "cleanupPolicy",
-                          "ref": <select
-                            name="cleanupPolicy"
-                          >
-                            <option
-                              selected=""
-                              value="delete"
-                            >
-                              Delete
-                            </option>
-                            <option
-                              value="compact"
-                            >
-                              Compact
-                            </option>
-                          </select>,
-                          "value": "delete",
-                        },
-                      },
-                      "customParams": Array [],
-                      "maxMessageBytes": Object {
-                        "_f": Object {
-                          "mount": true,
-                          "name": "maxMessageBytes",
-                          "ref": <input
-                            class="input"
-                            name="maxMessageBytes"
-                            type="number"
-                            value="1000012"
-                          />,
-                          "required": "Maximum message size in bytes is required",
-                          "value": "1000012",
-                        },
-                      },
-                      "minInSyncReplicas": Object {
-                        "_f": Object {
-                          "mount": true,
-                          "name": "minInSyncReplicas",
-                          "ref": <input
-                            class="input"
-                            name="minInSyncReplicas"
-                            placeholder="Min In Sync Replicas"
-                            type="number"
-                            value="1"
-                          />,
-                          "required": "Min In Sync Replicas is required.",
-                          "value": "1",
-                        },
-                      },
-                      "name": Object {
-                        "_f": Object {
-                          "mount": true,
-                          "name": "name",
-                          "pattern": Object {
-                            "message": "Only alphanumeric, _, -, and . allowed",
-                            "value": /\\^\\[\\.,A-Za-z0-9_-\\]\\+\\$/,
-                          },
-                          "ref": <input
-                            autocomplete="off"
-                            class="input"
-                            name="name"
-                            placeholder="Topic Name"
-                            value=""
-                          />,
-                          "required": "Topic Name is required.",
-                          "value": "",
-                        },
-                      },
-                      "partitions": Object {
-                        "_f": Object {
-                          "mount": true,
-                          "name": "partitions",
-                          "ref": <input
-                            class="input"
-                            name="partitions"
-                            placeholder="Number of partitions"
-                            type="number"
-                            value="1"
-                          />,
-                          "required": "Number of partitions is required.",
-                          "value": "1",
-                        },
-                      },
-                      "replicationFactor": Object {
-                        "_f": Object {
-                          "mount": true,
-                          "name": "replicationFactor",
-                          "ref": <input
-                            class="input"
-                            name="replicationFactor"
-                            placeholder="Replication Factor"
-                            type="number"
-                            value="1"
-                          />,
-                          "required": "Replication Factor is required.",
-                          "value": "1",
-                        },
-                      },
-                      "retentionBytes": Object {
-                        "_f": Object {
-                          "mount": true,
-                          "name": "retentionBytes",
-                          "ref": <select
-                            name="retentionBytes"
-                          >
-                            <option
-                              selected=""
-                              value="-1"
-                            >
-                              Not Set
-                            </option>
-                            <option
-                              value="1073741824"
-                            >
-                              1 GB
-                            </option>
-                            <option
-                              value="10737418240"
-                            >
-                              10 GB
-                            </option>
-                            <option
-                              value="21474836480"
-                            >
-                              20 GB
-                            </option>
-                            <option
-                              value="53687091200"
-                            >
-                              50 GB
-                            </option>
-                          </select>,
-                          "value": "-1",
-                        },
-                      },
-                      "retentionMs": Object {
-                        "_f": Object {
-                          "min": Object {
-                            "message": "must be greater than or equal to -1",
-                            "value": -1,
-                          },
-                          "mount": true,
-                          "name": "retentionMs",
-                          "ref": <input
-                            class="input"
-                            id="timeToRetain"
-                            name="retentionMs"
-                            type="number"
-                            value="604800000"
-                          />,
-                          "value": "604800000",
-                        },
-                      },
-                    },
-                  },
-                  "fieldsWithValidationRef": Object {
-                    "current": Object {
-                      "maxMessageBytes": true,
-                      "minInSyncReplicas": true,
-                      "name": true,
-                      "partitions": true,
-                      "replicationFactor": true,
-                      "retentionMs": true,
-                    },
-                  },
-                  "formStateRef": Object {
-                    "current": Object {
-                      "dirtyFields": Object {},
-                      "errors": Object {},
-                      "isDirty": false,
-                      "isSubmitSuccessful": false,
-                      "isSubmitted": false,
-                      "isSubmitting": false,
-                      "isValid": false,
-                      "isValidating": false,
-                      "submitCount": 0,
-                      "touchedFields": Object {},
-                    },
-                  },
-                  "formStateSubjectRef": Object {
-                    "current": Re {
-                      "observers": Array [
-                        ke {
-                          "closed": false,
-                          "observer": Object {
-                            "next": [Function],
-                          },
-                        },
-                      ],
-                    },
-                  },
-                  "getIsDirty": [Function],
-                  "inFieldArrayActionRef": Object {
-                    "current": false,
-                  },
-                  "isWatchAllRef": Object {
-                    "current": false,
-                  },
-                  "readFormStateRef": Object {
-                    "current": Object {
-                      "dirtyFields": false,
-                      "errors": "all",
-                      "isDirty": false,
-                      "isSubmitting": "all",
-                      "isValid": false,
-                      "isValidating": false,
-                      "touchedFields": false,
-                    },
-                  },
-                  "register": [Function],
-                  "shouldUnmount": undefined,
-                  "unregister": [Function],
-                  "validFieldsRef": Object {
-                    "current": Object {},
-                  },
-                  "watchFieldsRef": Object {
-                    "current": Set {
-                      "retentionMs",
-                    },
-                  },
-                  "watchInternal": [Function],
-                  "watchSubjectRef": Object {
-                    "current": Re {
-                      "observers": Array [],
-                    },
-                  },
-                }
-              }
-              formState={
-                Object {
-                  "dirtyFields": Object {},
-                  "errors": Object {},
-                  "isDirty": false,
-                  "isSubmitSuccessful": false,
-                  "isSubmitted": false,
-                  "isSubmitting": false,
-                  "isValid": false,
-                  "isValidating": false,
-                  "submitCount": 0,
-                  "touchedFields": Object {},
-                }
-              }
-              getValues={[Function]}
-              handleSubmit={[Function]}
-              register={[Function]}
-              reset={[Function]}
-              setError={[Function]}
-              setFocus={[Function]}
-              setValue={[Function]}
-              trigger={[Function]}
-              unregister={[Function]}
-              watch={[Function]}
-            >
-              <TopicForm
-                isSubmitting={false}
-                onSubmit={[Function]}
-              >
-                <form
-                  onSubmit={[Function]}
-                >
-                  <fieldset
-                    disabled={false}
-                  >
-                    <fieldset>
-                      <div
-                        className="columns"
-                      >
-                        <div
-                          className="column is-three-quarters"
-                        >
-                          <label
-                            className="label"
-                          >
-                            Topic Name *
-                          </label>
-                          <input
-                            autoComplete="off"
-                            className="input"
-                            name="name"
-                            onBlur={[Function]}
-                            onChange={[Function]}
-                            placeholder="Topic Name"
-                          />
-                          <p
-                            className="help is-danger"
-                          >
-                            <Component
-                              errors={Object {}}
-                              name="name"
-                            />
-                          </p>
-                        </div>
-                        <div
-                          className="column"
-                        >
-                          <label
-                            className="label"
-                          >
-                            Number of partitions *
-                          </label>
-                          <input
-                            className="input"
-                            defaultValue="1"
-                            name="partitions"
-                            onBlur={[Function]}
-                            onChange={[Function]}
-                            placeholder="Number of partitions"
-                            type="number"
-                          />
-                          <p
-                            className="help is-danger"
-                          >
-                            <Component
-                              errors={Object {}}
-                              name="partitions"
-                            />
-                          </p>
-                        </div>
-                      </div>
-                    </fieldset>
-                    <div
-                      className="columns"
-                    >
-                      <div
-                        className="column"
-                      >
-                        <label
-                          className="label"
-                        >
-                          Replication Factor *
-                        </label>
-                        <input
-                          className="input"
-                          defaultValue="1"
-                          name="replicationFactor"
-                          onBlur={[Function]}
-                          onChange={[Function]}
-                          placeholder="Replication Factor"
-                          type="number"
-                        />
-                        <p
-                          className="help is-danger"
-                        >
-                          <Component
-                            errors={Object {}}
-                            name="replicationFactor"
-                          />
-                        </p>
-                      </div>
-                      <div
-                        className="column"
-                      >
-                        <label
-                          className="label"
-                        >
-                          Min In Sync Replicas *
-                        </label>
-                        <input
-                          className="input"
-                          defaultValue="1"
-                          name="minInSyncReplicas"
-                          onBlur={[Function]}
-                          onChange={[Function]}
-                          placeholder="Min In Sync Replicas"
-                          type="number"
-                        />
-                        <p
-                          className="help is-danger"
-                        >
-                          <Component
-                            errors={Object {}}
-                            name="minInSyncReplicas"
-                          />
-                        </p>
-                      </div>
-                    </div>
-                    <div
-                      className="columns"
-                    >
-                      <div
-                        className="column is-one-third"
-                      >
-                        <label
-                          className="label"
-                        >
-                          Cleanup policy
-                        </label>
-                        <div
-                          className="select is-block"
-                        >
-                          <select
-                            defaultValue="delete"
-                            name="cleanupPolicy"
-                            onBlur={[Function]}
-                            onChange={[Function]}
-                          >
-                            <option
-                              value="delete"
-                            >
-                              Delete
-                            </option>
-                            <option
-                              value="compact"
-                            >
-                              Compact
-                            </option>
-                          </select>
-                        </div>
-                      </div>
-                      <div
-                        className="column is-one-third"
-                      >
-                        <TimeToRetain
-                          isSubmitting={false}
-                        >
-                          <label
-                            className="label is-flex"
-                            style={
-                              Object {
-                                "justifyContent": "space-between",
-                              }
-                            }
-                          >
-                            <div>
-                              Time to retain data (in ms)
-                            </div>
-                            <span
-                              className="has-text-info"
-                            >
-                              7d
-                            </span>
-                          </label>
-                          <input
-                            className="input"
-                            defaultValue={604800000}
-                            disabled={false}
-                            id="timeToRetain"
-                            name="retentionMs"
-                            onBlur={[Function]}
-                            onChange={[Function]}
-                            type="number"
-                          />
-                          <p
-                            className="help is-danger"
-                          >
-                            <Component
-                              errors={Object {}}
-                              name="retentionMs"
-                            />
-                          </p>
-                          <TimeToRetainBtns
-                            name="retentionMs"
-                            value="604800000"
-                          >
-                            <div
-                              className="buttons are-small"
-                            >
-                              <TimeToRetainBtn
-                                inputName="retentionMs"
-                                text="12h"
-                                value={43200000}
-                              >
-                                <button
-                                  className="button"
-                                  onClick={[Function]}
-                                  type="button"
-                                >
-                                  12h
-                                </button>
-                              </TimeToRetainBtn>
-                              <TimeToRetainBtn
-                                inputName="retentionMs"
-                                text="1d"
-                                value={86400000}
-                              >
-                                <button
-                                  className="button"
-                                  onClick={[Function]}
-                                  type="button"
-                                >
-                                  1d
-                                </button>
-                              </TimeToRetainBtn>
-                              <TimeToRetainBtn
-                                inputName="retentionMs"
-                                text="2d"
-                                value={172800000}
-                              >
-                                <button
-                                  className="button"
-                                  onClick={[Function]}
-                                  type="button"
-                                >
-                                  2d
-                                </button>
-                              </TimeToRetainBtn>
-                              <TimeToRetainBtn
-                                inputName="retentionMs"
-                                text="7d"
-                                value={604800000}
-                              >
-                                <button
-                                  className="button is-info"
-                                  onClick={[Function]}
-                                  type="button"
-                                >
-                                  7d
-                                </button>
-                              </TimeToRetainBtn>
-                              <TimeToRetainBtn
-                                inputName="retentionMs"
-                                text="4w"
-                                value={14515200000}
-                              >
-                                <button
-                                  className="button"
-                                  onClick={[Function]}
-                                  type="button"
-                                >
-                                  4w
-                                </button>
-                              </TimeToRetainBtn>
-                            </div>
-                          </TimeToRetainBtns>
-                        </TimeToRetain>
-                      </div>
-                      <div
-                        className="column is-one-third"
-                      >
-                        <label
-                          className="label"
-                        >
-                          Max size on disk in GB
-                        </label>
-                        <div
-                          className="select is-block"
-                        >
-                          <select
-                            defaultValue={-1}
-                            name="retentionBytes"
-                            onBlur={[Function]}
-                            onChange={[Function]}
-                          >
-                            <option
-                              value={-1}
-                            >
-                              Not Set
-                            </option>
-                            <option
-                              value={1073741824}
-                            >
-                              1 GB
-                            </option>
-                            <option
-                              value={10737418240}
-                            >
-                              10 GB
-                            </option>
-                            <option
-                              value={21474836480}
-                            >
-                              20 GB
-                            </option>
-                            <option
-                              value={53687091200}
-                            >
-                              50 GB
-                            </option>
-                          </select>
-                        </div>
-                      </div>
-                    </div>
-                    <div
-                      className="columns"
-                    >
-                      <div
-                        className="column"
-                      >
-                        <label
-                          className="label"
-                        >
-                          Maximum message size in bytes *
-                        </label>
-                        <input
-                          className="input"
-                          defaultValue="1000012"
-                          name="maxMessageBytes"
-                          onBlur={[Function]}
-                          onChange={[Function]}
-                          type="number"
-                        />
-                        <p
-                          className="help is-danger"
-                        >
-                          <Component
-                            errors={Object {}}
-                            name="maxMessageBytes"
-                          />
-                        </p>
-                      </div>
-                    </div>
-                    <withRouter(Connect(CustomParams))
-                      isSubmitting={false}
-                    >
-                      <Connect(CustomParams)
-                        history={
-                          Object {
-                            "action": "POP",
-                            "block": [Function],
-                            "createHref": [Function],
-                            "go": [Function],
-                            "goBack": [Function],
-                            "goForward": [Function],
-                            "listen": [Function],
-                            "location": Object {
-                              "hash": "",
-                              "pathname": "/ui/clusters/local/topics/create_new",
-                              "search": "",
-                            },
-                            "push": [Function],
-                            "replace": [Function],
-                          }
-                        }
-                        isSubmitting={false}
-                        location={
-                          Object {
-                            "hash": "",
-                            "pathname": "/ui/clusters/local/topics/create_new",
-                            "search": "",
-                          }
-                        }
-                        match={
-                          Object {
-                            "isExact": false,
-                            "params": Object {},
-                            "path": "/",
-                            "url": "/",
-                          }
-                        }
-                        staticContext={Object {}}
-                      >
-                        <CustomParams
-                          dispatch={[Function]}
-                          history={
-                            Object {
-                              "action": "POP",
-                              "block": [Function],
-                              "createHref": [Function],
-                              "go": [Function],
-                              "goBack": [Function],
-                              "goForward": [Function],
-                              "listen": [Function],
-                              "location": Object {
-                                "hash": "",
-                                "pathname": "/ui/clusters/local/topics/create_new",
-                                "search": "",
-                              },
-                              "push": [Function],
-                              "replace": [Function],
-                            }
-                          }
-                          isSubmitting={false}
-                          location={
-                            Object {
-                              "hash": "",
-                              "pathname": "/ui/clusters/local/topics/create_new",
-                              "search": "",
-                            }
-                          }
-                          match={
-                            Object {
-                              "isExact": false,
-                              "params": Object {},
-                              "path": "/",
-                              "url": "/",
-                            }
-                          }
-                          staticContext={Object {}}
-                        >
-                          <div
-                            className="columns"
-                          >
-                            <div
-                              className="column"
-                            >
-                              <CustomParamButton
-                                btnText="Add Custom Parameter"
-                                className="is-success"
-                                onClick={[Function]}
-                                type="fa-plus"
-                              >
-                                <button
-                                  className="button is-success is-outlined"
-                                  onClick={[Function]}
-                                  type="button"
-                                >
-                                  <span>
-                                    Add Custom Parameter
-                                  </span>
-                                  <span
-                                    className="icon"
-                                  >
-                                    <i
-                                      className="fas fa-lg fa-plus"
-                                    />
-                                  </span>
-                                </button>
-                              </CustomParamButton>
-                            </div>
-                          </div>
-                        </CustomParams>
-                      </Connect(CustomParams)>
-                    </withRouter(Connect(CustomParams))>
-                    <input
-                      className="button is-primary"
-                      type="submit"
-                    />
-                  </fieldset>
-                </form>
-              </TopicForm>
-            </Component>
-          </div>
-        </div>
-      </New>
-    </Provider>
-  </Router>
-</StaticRouter>
-`;

+ 1 - 1
kafka-ui-react-app/src/components/Topics/shared/Form/TopicForm.tsx

@@ -156,7 +156,7 @@ const TopicForm: React.FC<Props> = ({
 
         <CustomParamsContainer isSubmitting={isSubmitting} config={config} />
 
-        <input type="submit" className="button is-primary" />
+        <input type="submit" className="button is-primary" value="Send" />
       </fieldset>
     </form>
   );