github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/ui/src/app.spec.tsx (about)

     1  // Copyright 2020 The Cockroach Authors.
     2  //
     3  // Use of this software is governed by the Business Source License
     4  // included in the file licenses/BSL.txt.
     5  //
     6  // As of the Change Date specified in that file, in accordance with
     7  // the Business Source License, use of this software will be governed
     8  // by the Apache License, Version 2.0, included in the file
     9  // licenses/APL.txt.
    10  
    11  import React from "react";
    12  import { assert } from "chai";
    13  import { Action, Store } from "redux";
    14  import { createMemoryHistory } from "history";
    15  import { mount, ReactWrapper } from "enzyme";
    16  
    17  import "src/enzymeInit";
    18  import { App } from "src/app";
    19  import { AdminUIState, createAdminUIStore } from "src/redux/state";
    20  
    21  import ClusterOverview from "src/views/cluster/containers/clusterOverview";
    22  import NodeList from "src/views/clusterviz/containers/map/nodeList";
    23  import { ClusterVisualization } from "src/views/clusterviz/containers/map";
    24  import { NodeGraphs } from "src/views/cluster/containers/nodeGraphs";
    25  import { NodeOverview } from "src/views/cluster/containers/nodeOverview";
    26  import { Logs } from "src/views/cluster/containers/nodeLogs";
    27  import { EventPageUnconnected } from "src/views/cluster/containers/events";
    28  import { JobsTable } from "src/views/jobs";
    29  import {
    30    DatabaseGrantsList,
    31    DatabaseTablesList,
    32  } from "src/views/databases/containers/databases";
    33  import { TableMain } from "src/views/databases/containers/tableDetails";
    34  import { DataDistributionPage } from "src/views/cluster/containers/dataDistribution";
    35  import { StatementsPage } from "src/views/statements/statementsPage";
    36  import { StatementDetails } from "src/views/statements/statementDetails";
    37  import Debug from "src/views/reports/containers/debug";
    38  import { ReduxDebug } from "src/views/reports/containers/redux";
    39  import { CustomChart } from "src/views/reports/containers/customChart";
    40  import { EnqueueRange } from "src/views/reports/containers/enqueueRange";
    41  import { RangesMain } from "src/views/devtools/containers/raftRanges";
    42  import { RaftMessages } from "src/views/devtools/containers/raftMessages";
    43  import Raft from "src/views/devtools/containers/raft";
    44  import NotFound from "src/views/app/components/NotFound";
    45  import { ProblemRanges } from "src/views/reports/containers/problemRanges";
    46  import { Localities } from "src/views/reports/containers/localities";
    47  import { Nodes } from "src/views/reports/containers/nodes";
    48  import { DecommissionedNodeHistory } from "src/views/reports";
    49  import { Network } from "src/views/reports/containers/network";
    50  import { Settings } from "src/views/reports/containers/settings";
    51  import { Certificates } from "src/views/reports/containers/certificates";
    52  import { Range } from "src/views/reports/containers/range";
    53  import { Stores } from "src/views/reports/containers/stores";
    54  
    55  describe("Routing to", () => {
    56    const history = createMemoryHistory({
    57      initialEntries: ["/"],
    58    });
    59    const store: Store<AdminUIState, Action> = createAdminUIStore(history);
    60    const appWrapper: ReactWrapper = mount(<App history={history} store={store}/>);
    61  
    62    after(() => {
    63      appWrapper.unmount();
    64    });
    65  
    66    const navigateToPath = (path: string) => {
    67      history.push(path);
    68      appWrapper.update();
    69    };
    70  
    71    describe("'/' path", () => {
    72      it("routes to <ClusterOverview> component", () => {
    73        navigateToPath("/");
    74        assert.lengthOf(appWrapper.find(ClusterOverview), 1);
    75      });
    76  
    77      it("redirected to '/overview'", () => {
    78        navigateToPath("/");
    79        const location = history.location;
    80        assert.equal(location.pathname, "/overview/list");
    81      });
    82    });
    83  
    84    describe("'/overview' path", () => {
    85      it("routes to <ClusterOverview> component", () => {
    86        navigateToPath("/overview");
    87        assert.lengthOf(appWrapper.find(ClusterOverview), 1);
    88      });
    89  
    90      it("redirected to '/overview'", () => {
    91        navigateToPath("/overview");
    92        const location = history.location;
    93        assert.equal(location.pathname, "/overview/list");
    94      });
    95    });
    96  
    97    describe("'/overview/list' path", () => {
    98      it("routes to <NodeList> component", () => {
    99        navigateToPath("/overview");
   100        const clusterOverview = appWrapper.find(ClusterOverview);
   101        assert.lengthOf(clusterOverview, 1);
   102        const nodeList = clusterOverview.find(NodeList);
   103        assert.lengthOf(nodeList, 1);
   104      });
   105    });
   106  
   107    describe("'/overview/map' path", () => {
   108      it("routes to <ClusterViz> component", () => {
   109        navigateToPath("/overview/map");
   110        const clusterOverview = appWrapper.find(ClusterOverview);
   111        const clusterViz = appWrapper.find(ClusterVisualization);
   112        assert.lengthOf(clusterOverview, 1);
   113        assert.lengthOf(clusterViz, 1);
   114      });
   115    });
   116  
   117    { /* time series metrics */}
   118    describe("'/metrics' path", () => {
   119      it("routes to <NodeGraphs> component", () => {
   120        navigateToPath("/metrics");
   121        assert.lengthOf(appWrapper.find(NodeGraphs), 1);
   122      });
   123  
   124      it("redirected to '/metrics/overview/cluster'", () => {
   125        navigateToPath("/metrics");
   126        const location = history.location;
   127        assert.equal(location.pathname, "/metrics/overview/cluster");
   128      });
   129    });
   130  
   131    describe("'/metrics/overview/cluster' path", () => {
   132      it("routes to <NodeGraphs> component", () => {
   133        navigateToPath("/metrics/overview/cluster");
   134        assert.lengthOf(appWrapper.find(NodeGraphs), 1);
   135      });
   136    });
   137  
   138    describe("'/metrics/overview/node' path", () => {
   139      it("routes to <NodeGraphs> component", () => {
   140        navigateToPath("/metrics/overview/node");
   141        assert.lengthOf(appWrapper.find(NodeGraphs), 1);
   142      });
   143    });
   144  
   145    describe("'/metrics/:dashboardNameAttr' path", () => {
   146      it("routes to <NodeGraphs> component", () => {
   147        navigateToPath("/metrics/some-dashboard");
   148        assert.lengthOf(appWrapper.find(NodeGraphs), 1);
   149      });
   150  
   151      it("redirected to '/metrics/:${dashboardNameAttr}/cluster'", () => {
   152        navigateToPath("/metrics/some-dashboard");
   153        const location = history.location;
   154        assert.equal(location.pathname, "/metrics/some-dashboard/cluster");
   155      });
   156    });
   157  
   158    describe("'/metrics/:dashboardNameAttr/cluster' path", () => {
   159      it("routes to <NodeGraphs> component", () => {
   160        navigateToPath("/metrics/some-dashboard/cluster");
   161        assert.lengthOf(appWrapper.find(NodeGraphs), 1);
   162      });
   163    });
   164  
   165    describe("'/metrics/:dashboardNameAttr/node' path", () => {
   166      it("routes to <NodeGraphs> component", () => {
   167        navigateToPath("/metrics/some-dashboard/node");
   168        assert.lengthOf(appWrapper.find(NodeGraphs), 1);
   169      });
   170  
   171      it("redirected to '/metrics/:${dashboardNameAttr}/cluster'", () => {
   172        navigateToPath("/metrics/some-dashboard/node");
   173        const location = history.location;
   174        assert.equal(location.pathname, "/metrics/some-dashboard/cluster");
   175      });
   176    });
   177  
   178    describe("'/metrics/:dashboardNameAttr/node/:nodeIDAttr' path", () => {
   179      it("routes to <NodeGraphs> component", () => {
   180        navigateToPath("/metrics/some-dashboard/node/123");
   181        assert.lengthOf(appWrapper.find(NodeGraphs), 1);
   182      });
   183    });
   184  
   185    { /* node details */}
   186    describe("'/node' path", () => {
   187      it("routes to <NodeList> component", () => {
   188        navigateToPath("/node");
   189        assert.lengthOf(appWrapper.find(NodeList), 1);
   190      });
   191  
   192      it("redirected to '/overview/list'", () => {
   193        navigateToPath("/node");
   194        const location = history.location;
   195        assert.equal(location.pathname, "/overview/list");
   196      });
   197    });
   198  
   199    describe("'/node/:nodeIDAttr' path", () => {
   200      it("routes to <NodeOverview> component", () => {
   201        navigateToPath("/node/1");
   202        assert.lengthOf(appWrapper.find(NodeOverview), 1);
   203      });
   204    });
   205  
   206    describe("'/node/:nodeIDAttr/logs' path", () => {
   207      it("routes to <Logs> component", () => {
   208        navigateToPath("/node/1/logs");
   209        assert.lengthOf(appWrapper.find(Logs), 1);
   210      });
   211    });
   212  
   213    { /* events & jobs */}
   214    describe("'/events' path", () => {
   215      it("routes to <EventPageUnconnected> component", () => {
   216        navigateToPath("/events");
   217        assert.lengthOf(appWrapper.find(EventPageUnconnected), 1);
   218      });
   219    });
   220  
   221    describe("'/jobs' path", () => {
   222      it("routes to <JobsTable> component", () => {
   223        navigateToPath("/jobs");
   224        assert.lengthOf(appWrapper.find(JobsTable), 1);
   225      });
   226    });
   227  
   228    { /* databases */}
   229    describe("'/databases' path", () => {
   230      it("routes to <DatabaseTablesList> component", () => {
   231        navigateToPath("/databases");
   232        assert.lengthOf(appWrapper.find(DatabaseTablesList), 1);
   233      });
   234  
   235      it("redirected to '/databases/tables'", () => {
   236        navigateToPath("/databases");
   237        const location = history.location;
   238        assert.equal(location.pathname, "/databases/tables");
   239      });
   240    });
   241  
   242    describe("'/databases/tables' path", () => {
   243      it("routes to <DatabaseTablesList> component", () => {
   244        navigateToPath("/databases/tables");
   245        assert.lengthOf(appWrapper.find(DatabaseTablesList), 1);
   246      });
   247    });
   248  
   249    describe("'/databases/grants' path", () => {
   250      it("routes to <DatabaseGrantsList> component", () => {
   251        navigateToPath("/databases/grants");
   252        assert.lengthOf(appWrapper.find(DatabaseGrantsList), 1);
   253      });
   254    });
   255  
   256    describe("'/databases/database/:${databaseNameAttr}/table/:${tableNameAttr}' path", () => {
   257      it("redirected to '/database/:${databaseNameAttr}/table/:${tableNameAttr}'", () => {
   258        navigateToPath("/databases/database/some-db-name/table/some-table-name");
   259        const location = history.location;
   260        assert.equal(location.pathname, "/database/some-db-name/table/some-table-name");
   261      });
   262    });
   263  
   264    describe("'/database' path", () => {
   265      it("redirected to '/databases'", () => {
   266        navigateToPath("/databases/tables");
   267        const location = history.location;
   268        assert.equal(location.pathname, "/databases/tables");
   269      });
   270    });
   271  
   272    describe("'/database/:${databaseNameAttr}' path", () => {
   273      it("redirected to '/databases'", () => {
   274        navigateToPath("/database/some-db-name");
   275        const location = history.location;
   276        assert.equal(location.pathname, "/databases/tables");
   277      });
   278    });
   279  
   280    describe("'/database/:${databaseNameAttr}/table' path", () => {
   281      it("redirected to '/databases/tables'", () => {
   282        navigateToPath("/database/some-db-name/table");
   283        const location = history.location;
   284        assert.equal(location.pathname, "/databases/tables");
   285      });
   286    });
   287  
   288    describe("'/database/:${databaseNameAttr}/table/:${tableNameAttr}' path", () => {
   289      it("routes to <TableMain> component", () => {
   290        navigateToPath("/database/some-db-name/table/some-table-name");
   291        assert.lengthOf(appWrapper.find(TableMain), 1);
   292      });
   293    });
   294  
   295    { /* data distribution */}
   296    describe("'/data-distribution' path", () => {
   297      it("routes to <DataDistributionPage> component", () => {
   298        navigateToPath("/data-distribution");
   299        assert.lengthOf(appWrapper.find(DataDistributionPage), 1);
   300      });
   301    });
   302  
   303    { /* statement statistics */}
   304    describe("'/statements' path", () => {
   305      it("routes to <StatementsPage> component", () => {
   306        navigateToPath("/statements");
   307        assert.lengthOf(appWrapper.find(StatementsPage), 1);
   308      });
   309    });
   310  
   311    describe("'/statements/:${appAttr}' path", () => {
   312      it("routes to <StatementsPage> component", () => {
   313        navigateToPath("/statements/(internal)");
   314        assert.lengthOf(appWrapper.find(StatementsPage), 1);
   315      });
   316    });
   317  
   318    describe("'/statements/:${appAttr}/:${statementAttr}' path", () => {
   319      it("routes to <StatementDetails> component", () => {
   320        navigateToPath("/statements/(internal)/true");
   321        assert.lengthOf(appWrapper.find(StatementDetails), 1);
   322      });
   323    });
   324  
   325    describe("'/statements/:${implicitTxnAttr}/:${statementAttr}' path", () => {
   326      it("routes to <StatementDetails> component", () => {
   327        navigateToPath("/statements/implicit-txn-attr/statement-attr");
   328        assert.lengthOf(appWrapper.find(StatementDetails), 1);
   329      });
   330    });
   331  
   332    describe("'/statement' path", () => {
   333      it("redirected to '/statements'", () => {
   334        navigateToPath("/statement");
   335        const location = history.location;
   336        assert.equal(location.pathname, "/statements");
   337      });
   338    });
   339  
   340    describe("'/statement/:${statementAttr}' path", () => {
   341      it("routes to <StatementDetails> component", () => {
   342        navigateToPath("/statement/statement-attr");
   343        assert.lengthOf(appWrapper.find(StatementDetails), 1);
   344      });
   345    });
   346  
   347    describe("'/statement/:${implicitTxnAttr}/:${statementAttr}' path", () => {
   348      it("routes to <StatementDetails> component", () => {
   349        navigateToPath("/statement/implicit-attr/statement-attr/");
   350        assert.lengthOf(appWrapper.find(StatementDetails), 1);
   351      });
   352    });
   353  
   354    { /* debug pages */}
   355    describe("'/debug' path", () => {
   356      it("routes to <Debug> component", () => {
   357        navigateToPath("/debug");
   358        assert.lengthOf(appWrapper.find(Debug), 1);
   359      });
   360    });
   361  
   362    // TODO (koorosh): Disabled due to strange failure on internal
   363    // behavior of ReduxDebug component under test env.
   364    xdescribe("'/debug/redux' path", () => {
   365      it("routes to <ReduxDebug> component", () => {
   366        navigateToPath("/debug/redux");
   367        assert.lengthOf(appWrapper.find(ReduxDebug), 1);
   368      });
   369    });
   370  
   371    describe("'/debug/chart' path", () => {
   372      it("routes to <CustomChart> component", () => {
   373        navigateToPath("/debug/chart");
   374        // assert.lengthOf(appWrapper.find(Debug), 1);
   375        assert.lengthOf(appWrapper.find(CustomChart), 1);
   376      });
   377    });
   378  
   379    describe("'/debug/enqueue_range' path", () => {
   380      it("routes to <EnqueueRange> component", () => {
   381        navigateToPath("/debug/enqueue_range");
   382        assert.lengthOf(appWrapper.find(EnqueueRange), 1);
   383      });
   384    });
   385  
   386    { /* raft pages */}
   387    describe("'/raft' path", () => {
   388      it("routes to <Raft> component", () => {
   389        navigateToPath("/raft");
   390        assert.lengthOf(appWrapper.find(Raft), 1);
   391      });
   392  
   393      it("redirected to '/raft/ranges'", () => {
   394        navigateToPath("/raft");
   395        const location = history.location;
   396        assert.equal(location.pathname, "/raft/ranges");
   397      });
   398    });
   399  
   400    describe("'/raft/ranges' path", () => {
   401      it("routes to <RangesMain> component", () => {
   402        navigateToPath("/raft/ranges");
   403        assert.lengthOf(appWrapper.find(RangesMain), 1);
   404      });
   405    });
   406  
   407    describe("'/raft/messages/all' path", () => {
   408      it("routes to <RaftMessages> component", () => {
   409        navigateToPath("/raft/messages/all");
   410        assert.lengthOf(appWrapper.find(RaftMessages), 1);
   411      });
   412    });
   413  
   414    describe("'/raft/messages/node/:${nodeIDAttr}' path", () => {
   415      it("routes to <RaftMessages> component", () => {
   416        navigateToPath("/raft/messages/node/node-id-attr");
   417        assert.lengthOf(appWrapper.find(RaftMessages), 1);
   418      });
   419    });
   420  
   421    describe("'/reports/problemranges' path", () => {
   422      it("routes to <ProblemRanges> component", () => {
   423        navigateToPath("/reports/problemranges");
   424        assert.lengthOf(appWrapper.find(ProblemRanges), 1);
   425      });
   426    });
   427  
   428    describe("'/reports/problemranges/:nodeIDAttr' path", () => {
   429      it("routes to <ProblemRanges> component", () => {
   430        navigateToPath("/reports/problemranges/1");
   431        assert.lengthOf(appWrapper.find(ProblemRanges), 1);
   432      });
   433    });
   434  
   435    describe("'/reports/localities' path", () => {
   436      it("routes to <Localities> component", () => {
   437        navigateToPath("/reports/localities");
   438        assert.lengthOf(appWrapper.find(Localities), 1);
   439      });
   440    });
   441  
   442    describe("'/reports/nodes' path", () => {
   443      it("routes to <Nodes> component", () => {
   444        navigateToPath("/reports/nodes");
   445        assert.lengthOf(appWrapper.find(Nodes), 1);
   446      });
   447    });
   448  
   449    describe("'/reports/nodes/history' path", () => {
   450      it("routes to <DecommissionedNodeHistory> component", () => {
   451        navigateToPath("/reports/nodes/history");
   452        assert.lengthOf(appWrapper.find(DecommissionedNodeHistory), 1);
   453      });
   454    });
   455  
   456    describe("'/reports/network' path", () => {
   457      it("routes to <Network> component", () => {
   458        navigateToPath("/reports/network");
   459        assert.lengthOf(appWrapper.find(Network), 1);
   460      });
   461    });
   462  
   463    describe("'/reports/network/:nodeIDAttr' path", () => {
   464      it("routes to <Network> component", () => {
   465        navigateToPath("/reports/network/1");
   466        assert.lengthOf(appWrapper.find(Network), 1);
   467      });
   468    });
   469  
   470    describe("'/reports/settings' path", () => {
   471      it("routes to <Settings> component", () => {
   472        navigateToPath("/reports/settings");
   473        assert.lengthOf(appWrapper.find(Settings), 1);
   474      });
   475    });
   476  
   477    describe("'/reports/certificates/:nodeIDAttr' path", () => {
   478      it("routes to <Certificates> component", () => {
   479        navigateToPath("/reports/certificates/1");
   480        assert.lengthOf(appWrapper.find(Certificates), 1);
   481      });
   482    });
   483  
   484    describe("'/reports/range/:nodeIDAttr' path", () => {
   485      it("routes to <Range> component", () => {
   486        navigateToPath("/reports/range/1");
   487        assert.lengthOf(appWrapper.find(Range), 1);
   488      });
   489    });
   490  
   491    describe("'/reports/stores/:nodeIDAttr' path", () => {
   492      it("routes to <Stores> component", () => {
   493        navigateToPath("/reports/stores/1");
   494        assert.lengthOf(appWrapper.find(Stores), 1);
   495      });
   496    });
   497  
   498    { /* old route redirects */}
   499    describe("'/cluster' path", () => {
   500      it("redirected to '/metrics/overview/cluster'", () => {
   501        navigateToPath("/cluster");
   502        const location = history.location;
   503        assert.equal(location.pathname, "/metrics/overview/cluster");
   504      });
   505    });
   506  
   507    describe("'/cluster/all/:${dashboardNameAttr}' path", () => {
   508      it("redirected to '/metrics/:${dashboardNameAttr}/cluster'", () => {
   509        const dashboardNameAttr = "some-dashboard-name";
   510        navigateToPath(`/cluster/all/${dashboardNameAttr}`);
   511        const location = history.location;
   512        assert.equal(location.pathname, `/metrics/${dashboardNameAttr}/cluster`);
   513      });
   514    });
   515  
   516    describe("'/cluster/node/:${nodeIDAttr}/:${dashboardNameAttr}' path", () => {
   517      it("redirected to '/metrics/:${dashboardNameAttr}/cluster'", () => {
   518        const dashboardNameAttr = "some-dashboard-name";
   519        const nodeIDAttr = 1;
   520        navigateToPath(`/cluster/node/${nodeIDAttr}/${dashboardNameAttr}`);
   521        const location = history.location;
   522        assert.equal(location.pathname, `/metrics/${dashboardNameAttr}/node/${nodeIDAttr}`);
   523      });
   524    });
   525  
   526    describe("'/cluster/nodes' path", () => {
   527      it("redirected to '/overview/list'", () => {
   528        navigateToPath("/cluster/nodes");
   529        const location = history.location;
   530        assert.equal(location.pathname, "/overview/list");
   531      });
   532    });
   533  
   534    describe("'/cluster/nodes/:${nodeIDAttr}' path", () => {
   535      it("redirected to '/node/:${nodeIDAttr}'", () => {
   536        const nodeIDAttr = 1;
   537        navigateToPath(`/cluster/nodes/${nodeIDAttr}`);
   538        const location = history.location;
   539        assert.equal(location.pathname, `/node/${nodeIDAttr}`);
   540      });
   541    });
   542  
   543    describe("'/cluster/nodes/:${nodeIDAttr}/logs' path", () => {
   544      it("redirected to '/node/:${nodeIDAttr}/logs'", () => {
   545        const nodeIDAttr = 1;
   546        navigateToPath(`/cluster/nodes/${nodeIDAttr}/logs`);
   547        const location = history.location;
   548        assert.equal(location.pathname, `/node/${nodeIDAttr}/logs`);
   549      });
   550    });
   551  
   552    describe("'/cluster/events' path", () => {
   553      it("redirected to '/events'", () => {
   554        navigateToPath("/cluster/events");
   555        const location = history.location;
   556        assert.equal(location.pathname, "/events");
   557      });
   558    });
   559  
   560    describe("'/cluster/nodes' path", () => {
   561      it("redirected to '/overview/list'", () => {
   562        navigateToPath("/cluster/nodes");
   563        const location = history.location;
   564        assert.equal(location.pathname, "/overview/list");
   565      });
   566    });
   567  
   568    describe("'/unknown-url' path", () => {
   569      it("routes to <NotFound> component", () => {
   570        navigateToPath("/some-random-ulr");
   571        assert.lengthOf(appWrapper.find(NotFound), 1);
   572      });
   573    });
   574  });