• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

mac-s-g / react-json-view / #1391

13 Jul 2021 07:26AM UTC coverage: 77.495% (-5.6%) from 83.138%
#1391

push

Rahul R
shouldComponentUpdate Logic change

285 of 376 branches covered (75.8%)

Branch coverage included in aggregate %.

0 of 4 new or added lines in 1 file covered. (0.0%)

47 existing lines in 3 files now uncovered.

507 of 646 relevant lines covered (78.48%)

41.68 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

87.32
/src/js/components/DataTypes/Object.js
1
import React from 'react';
2
import { polyfill } from 'react-lifecycles-compat';
3
import { toType } from './../../helpers/util';
4

5
//data type components
6
import { JsonObject } from './DataTypes';
7

8
import VariableEditor from './../VariableEditor';
9
import VariableMeta from './../VariableMeta';
10
import ArrayGroup from './../ArrayGroup';
11
import OptimizedArrayGroup from './../OptimizedArrayGroup';
12
import ObjectName from './../ObjectName';
13

14
//attribute store
15
import AttributeStore from './../../stores/ObjectAttributes';
16

17
//icons
18
import { CollapsedIcon, ExpandedIcon } from './../ToggleIcons';
19

20
//theme
21
import Theme from './../../themes/getStyle';
22

23
//increment 1 with each nested object & array
24
const DEPTH_INCREMENT = 1;
1✔
25
//single indent is 5px
26
const SINGLE_INDENT = 5;
1✔
27

28
class RjvObject extends React.PureComponent {
29
    constructor(props) {
30
        super(props);
46✔
31
        const state = RjvObject.getState(props);
46✔
32
        this.state = {
46✔
33
            ...state,
34
            prevProps: {}
35
        };
36
    }
37

38
    static getState = props => {
1✔
39
        const size = Object.keys(props.src).length;
100✔
40
        const expanded =
41
            (props.collapsed === false ||
100✔
42
                (props.collapsed !== true && props.collapsed > props.depth)) &&
43
            (!props.shouldCollapse ||
44
                props.shouldCollapse({
45
                    name: props.name,
46
                    src: props.src,
47
                    type: toType(props.src),
48
                    namespace: props.namespace
49
                }) === false) &&
50
            //initialize closed if object has no items
51
            size !== 0;
52
        const state = {
100✔
53
            expanded: AttributeStore.get(
54
                props.rjvId,
55
                props.namespace,
56
                'expanded',
57
                expanded
58
            ),
59
            object_type: props.type === 'array' ? 'array' : 'object',
100✔
60
            parent_type: props.type === 'array' ? 'array' : 'object',
100✔
61
            size,
62
            hovered: false
63
        };
64
        return state;
100✔
65
    };
66

67
    static getDerivedStateFromProps(nextProps, prevState) {
68
        const { prevProps } = prevState;
54✔
69
        if (
54!
70
            nextProps.src !== prevProps.src ||
75!
71
            nextProps.collapsed !== prevProps.collapsed ||
72
            nextProps.name !== prevProps.name ||
73
            nextProps.namespace !== prevProps.namespace ||
74
            nextProps.rjvId !== prevProps.rjvId
75
        ) {
76
            const newState = RjvObject.getState(nextProps);
54✔
77
            return {
54✔
78
                ...newState,
79
                prevProps: nextProps
80
            };
81
        }
UNCOV
82
        return null;
×
83
    }
84

85
    toggleCollapsed = () => {
46✔
UNCOV
86
        this.setState(
×
87
            {
88
                expanded: !this.state.expanded
89
            },
90
            () => {
UNCOV
91
                AttributeStore.set(
×
92
                    this.props.rjvId,
93
                    this.props.namespace,
94
                    'expanded',
95
                    this.state.expanded
96
                );
97
            }
98
        );
99
    };
100

101
    getObjectContent = (depth, src, props) => {
46✔
102
        return (
39✔
103
            <div class="pushed-content object-container">
104
                <div
105
                    class="object-content"
106
                    {...Theme(this.props.theme, 'pushed-content')}
107
                >
108
                    {this.renderObjectContents(src, props)}
109
                </div>
110
            </div>
111
        );
112
    };
113

114
    getEllipsis = () => {
46✔
115
        const { size } = this.state;
15✔
116

117
        if (size === 0) {
15✔
118
            //don't render an ellipsis when an object has no items
119
            return null;
7✔
120
        } else {
121
            return (
8✔
122
                <div
123
                    {...Theme(this.props.theme, 'ellipsis')}
124
                    class="node-ellipsis"
125
                    onClick={this.toggleCollapsed}
126
                >
127
                    ...
128
                </div>
129
            );
130
        }
131
    };
132

133
    getObjectMetaData = src => {
46✔
134
        const { rjvId, theme } = this.props;
54✔
135
        const { size, hovered } = this.state;
54✔
136
        return (
54✔
137
            <VariableMeta rowHovered={hovered} size={size} {...this.props} />
138
        );
139
    };
140

141
    getBraceStart(object_type, expanded) {
142
        const { src, theme, iconStyle, parent_type } = this.props;
54✔
143

144
        if (parent_type === 'array_group') {
54✔
145
            return (
2✔
146
                <span>
147
                    <span {...Theme(theme, 'brace')}>
148
                        {object_type === 'array' ? '[' : '{'}
2!
149
                    </span>
150
                    {expanded ? this.getObjectMetaData(src) : null}
2!
151
                </span>
152
            );
153
        }
154

155
        const IconComponent = expanded ? ExpandedIcon : CollapsedIcon;
52✔
156

157
        return (
52✔
158
            <span>
159
                <span
160
                    onClick={e => {
UNCOV
161
                        this.toggleCollapsed();
×
162
                    }}
163
                    {...Theme(theme, 'brace-row')}
164
                >
165
                    <div
166
                        class="icon-container"
167
                        {...Theme(theme, 'icon-container')}
168
                    >
169
                        <IconComponent {...{ theme, iconStyle }} />
170
                    </div>
171
                    <ObjectName {...this.props} />
172
                    <span {...Theme(theme, 'brace')}>
173
                        {object_type === 'array' ? '[' : '{'}
52✔
174
                    </span>
175
                </span>
176
                {expanded ? this.getObjectMetaData(src) : null}
52✔
177
            </span>
178
        );
179
    }
180

181
    render() {
182
        // `indentWidth` and `collapsed` props will
183
        // perpetuate to children via `...rest`
184
        const {
185
            depth,
186
            src,
187
            namespace,
188
            name,
189
            type,
190
            parent_type,
191
            theme,
192
            jsvRoot,
193
            iconStyle,
194
            ...rest
195
        } = this.props;
54✔
196

197
        const { object_type, expanded } = this.state;
54✔
198

199
        let styles = {};
54✔
200
        if (!jsvRoot && parent_type !== 'array_group') {
54✔
201
            styles.paddingLeft = this.props.indentWidth * SINGLE_INDENT;
43✔
202
        } else if (parent_type === 'array_group') {
11✔
203
            styles.borderLeft = 0;
2✔
204
            styles.display = 'inline';
2✔
205
        }
206

207
        return (
54✔
208
            <div
209
                class="object-key-val"
210
                onMouseEnter={() =>
UNCOV
211
                    this.setState({ ...this.state, hovered: true })
×
212
                }
213
                onMouseLeave={() =>
UNCOV
214
                    this.setState({ ...this.state, hovered: false })
×
215
                }
216
                {...Theme(theme, jsvRoot ? 'jsv-root' : 'objectKeyVal', styles)}
54✔
217
            >
218
                {this.getBraceStart(object_type, expanded)}
219
                {expanded
54✔
220
                    ? this.getObjectContent(depth, src, {
221
                          theme,
222
                          iconStyle,
223
                          ...rest
224
                      })
225
                    : this.getEllipsis()}
226
                <span class="brace-row">
227
                    <span
228
                        style={{
229
                            ...Theme(theme, 'brace').style,
230
                            paddingLeft: expanded ? '3px' : '0px'
54✔
231
                        }}
232
                    >
233
                        {object_type === 'array' ? ']' : '}'}
54✔
234
                    </span>
235
                    {expanded ? null : this.getObjectMetaData(src)}
54✔
236
                </span>
237
            </div>
238
        );
239
    }
240

241
    renderObjectContents = (variables, props) => {
46✔
242
        const {
243
            depth,
244
            parent_type,
245
            index_offset,
246
            groupArraysAfterLength,
247
            namespace
248
        } = this.props;
39✔
249
        const { object_type } = this.state;
39✔
250
        let elements = [],
39✔
251
            variable;
252
        let keys = Object.keys(variables || {});
39!
253
        if (this.props.sortKeys && object_type !== 'array') {
39✔
254
            keys = keys.sort();
1✔
255
        }
256

257
        keys.forEach(name => {
39✔
258
            variable = new JsonVariable(name, variables[name]);
118✔
259

260
            if (parent_type === 'array_group' && index_offset) {
118✔
261
                variable.name = parseInt(variable.name) + index_offset;
2✔
262
            }
263
            if (!variables.hasOwnProperty(name)) {
118!
UNCOV
264
                return;
×
265
            } else if (variable.type === 'object') {
118✔
266
                elements.push(
12✔
267
                    <JsonObject
268
                        key={variable.name}
269
                        depth={depth + DEPTH_INCREMENT}
270
                        name={variable.name}
271
                        src={variable.value}
272
                        namespace={namespace.concat(variable.name)}
273
                        parent_type={object_type}
274
                        {...props}
275
                    />
276
                );
277
            } else if (variable.type === 'array') {
106✔
278
                let ObjectComponent = JsonObject;
13✔
279

280
                if (
13!
281
                    groupArraysAfterLength &&
23✔
282
                    variable.value.length > groupArraysAfterLength
283
                ) {
UNCOV
284
                    if(props.useOptimizedArray) ObjectComponent = OptimizedArrayGroup;
×
UNCOV
285
                    else ObjectComponent = ArrayGroup;
×
286
                }
287

288
                elements.push(
13✔
289
                    <ObjectComponent
290
                        key={variable.name}
291
                        depth={depth + DEPTH_INCREMENT}
292
                        name={variable.name}
293
                        src={variable.value}
294
                        namespace={namespace.concat(variable.name)}
295
                        type="array"
296
                        parent_type={object_type}
297
                        {...props}
298
                    />
299
                );
300
            } else {
301
                elements.push(
93✔
302
                    <VariableEditor
303
                        key={variable.name + '_' + namespace}
304
                        variable={variable}
305
                        singleIndent={SINGLE_INDENT}
306
                        namespace={namespace}
307
                        type={this.props.type}
308
                        {...props}
309
                    />
310
                );
311
            }
312
        });
313

314
        return elements;
39✔
315
    };
316
}
317

318
//just store name, value and type with a variable
319
class JsonVariable {
320
    constructor(name, value) {
321
        this.name = name;
118✔
322
        this.value = value;
118✔
323
        this.type = toType(value);
118✔
324
    }
325
}
326

327
polyfill(RjvObject);
1✔
328

329
//export component
330
export default RjvObject;
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc