github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/ui/src/views/shared/components/loading/loading.spec.tsx (about) 1 // Copyright 2018 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 _ from "lodash"; 12 import React from "react"; 13 import { assert } from "chai"; 14 15 import "src/enzymeInit"; 16 import Loading from "src/views/shared/components/loading"; 17 import { ReactWrapper, mount } from "enzyme"; 18 19 const LOADING_CLASS_NAME = "loading-class-name"; 20 const RENDER_CLASS_NAME = "render-class-name"; 21 const ERROR_CLASS_NAME = "loading-error"; 22 const ALL_CLASS_NAMES = [LOADING_CLASS_NAME, ERROR_CLASS_NAME, RENDER_CLASS_NAME]; 23 24 interface MakeLoadingProps { 25 loading: boolean; 26 error?: Error | Error[] | null; 27 renderClassName?: string; 28 } 29 30 interface AssertExpectedProps { 31 onlyVisibleClass: string; 32 errorCount?: number; 33 } 34 35 const makeLoadingComponent = (props: MakeLoadingProps) => mount( 36 <Loading 37 loading={props.loading} 38 error={props.error} 39 className={LOADING_CLASS_NAME} 40 render={() => (<div className={props.renderClassName || RENDER_CLASS_NAME}>Hello, world!</div>)} 41 />, 42 ); 43 44 describe("<Loading>", () => { 45 46 describe("when error is null", () => { 47 describe("when loading=false", () => { 48 it("renders content.", () => { 49 const wrapper = makeLoadingComponent({ 50 loading: false, error: null, 51 renderClassName: "my-rendered-content", 52 }); 53 assertExpectedState(wrapper, { 54 onlyVisibleClass: "my-rendered-content", 55 }); 56 }); 57 }); 58 59 describe("when loading=true", () => { 60 it("renders loading spinner.", () => { 61 const wrapper = makeLoadingComponent({ 62 loading: true, error: null, 63 }); 64 assertExpectedState(wrapper, { 65 onlyVisibleClass: LOADING_CLASS_NAME, 66 }); 67 }); 68 }); 69 }); 70 71 describe("when error is a single error", () => { 72 describe("when loading=false", () => { 73 it("renders error, regardless of loading value.", () => { 74 const wrapper = makeLoadingComponent({ 75 loading: false, 76 error: Error("some error message"), 77 }); 78 assertExpectedState(wrapper, { 79 onlyVisibleClass: ERROR_CLASS_NAME, 80 errorCount: 1, 81 }); 82 }); 83 }); 84 85 describe("when loading=true", () => { 86 it("renders error, regardless of loading value.", () => { 87 const wrapper = makeLoadingComponent({ 88 loading: true, 89 error: Error("some error message"), 90 }); 91 assertExpectedState(wrapper, { 92 onlyVisibleClass: ERROR_CLASS_NAME, 93 errorCount: 1, 94 }); 95 }); 96 }); 97 }); 98 99 describe("when error is a list of errors", () => { 100 describe("when no errors are null", () => { 101 it("renders all errors in list", () => { 102 const wrapper = makeLoadingComponent({ 103 loading: false, 104 error: [ 105 Error("error1"), 106 Error("error2"), 107 Error("error3"), 108 ], 109 }); 110 assertExpectedState(wrapper, { 111 onlyVisibleClass: ERROR_CLASS_NAME, 112 errorCount: 3, 113 }); 114 }); 115 }); 116 117 describe("when some errors are null", () => { 118 it("ignores null list values, rending only valid errors.", () => { 119 const wrapper = makeLoadingComponent({ 120 loading: false, 121 error: [ 122 null, 123 Error("error1"), 124 Error("error2"), 125 null, 126 Error("error3"), 127 null, 128 ], 129 }); 130 assertExpectedState(wrapper, { 131 onlyVisibleClass: ERROR_CLASS_NAME, 132 errorCount: 3, 133 }); 134 }); 135 }); 136 137 describe("when all errors are null", () => { 138 it("renders content, since there are no errors.", () => { 139 const wrapper = makeLoadingComponent({ 140 loading: false, 141 error: [ 142 null, 143 null, 144 null, 145 ], 146 renderClassName: "no-errors-so-should-render-me", 147 }); 148 assertExpectedState(wrapper, { 149 onlyVisibleClass: "no-errors-so-should-render-me", 150 }); 151 }); 152 }); 153 }); 154 }); 155 156 function assertExpectedState( 157 wrapper: ReactWrapper, 158 props: AssertExpectedProps, 159 ) { 160 // Assert that onlyVisibleClass is rendered, and that all classes are not. 161 _.map(ALL_CLASS_NAMES, (className) => { 162 const expectedVisibility = props.onlyVisibleClass === className; 163 const expectedLength = expectedVisibility ? 1 : 0; 164 const element = "div." + className; 165 assert.lengthOf( 166 wrapper.find(element), 167 expectedLength, "expected " + element + 168 (expectedVisibility ? " to be visible" : " to not be rendered")); 169 }); 170 171 if (props.errorCount) { 172 assert.lengthOf( 173 wrapper.find("div." + ERROR_CLASS_NAME).find("li"), 174 props.errorCount, 175 ); 176 } 177 }