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

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

16 Jun 2022 09:30AM UTC coverage: 82.117% (+1.4%) from 80.707%
#1397

push

zielinskipawel
param name typo

289 of 365 branches covered (79.18%)

Branch coverage included in aggregate %.

2 of 3 new or added lines in 1 file covered. (66.67%)

36 existing lines in 2 files now uncovered.

510 of 608 relevant lines covered (83.88%)

44.43 hits per line

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

81.33
/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 ObjectName from './../ObjectName';
12

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

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

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

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

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

37
    static getState = props => {
1✔
38
        const size = Object.keys(props.src).length;
100✔
39
        const expanded =
40
            (props.collapsed === false ||
100✔
41
                (props.collapsed !== true && props.collapsed > props.depth)) &&
42
            (!props.shouldCollapse ||
43
                props.shouldCollapse({
44
                    name: props.name,
45
                    src: props.src,
46
                    type: toType(props.src),
47
                    namespace: props.namespace
48
                }) === false) &&
49
            //initialize closed if object has no items
50
            size !== 0;
51
        const state = {
100✔
52
            expanded: AttributeStore.get(
53
                props.rjvId,
54
                props.namespace,
55
                'expanded',
56
                expanded
57
            ),
58
            object_type: props.type === 'array' ? 'array' : 'object',
100✔
59
            parent_type: props.type === 'array' ? 'array' : 'object',
100✔
60
            size,
61
            hovered: false,
62
            objectCollapsedMaxPropsCount: props.objectCollapsedMaxPropsCount
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
            () => {
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 = (parent_type, src, jsvRoot, objectCollapsedMaxPropsCount) => {
46✔
115
        const { size } = this.state;
15✔
116
        const isArray = src instanceof Array;
15✔
117
        const showMetadata =
118
            objectCollapsedMaxPropsCount &&
15!
119
            !isArray &&
120
            (jsvRoot || parent_type === 'object');
121
        debugger;
15✔
122
        let metadata = '...';
15✔
123
        let propsCount = 0;
15✔
124
        if (showMetadata) {
15!
UNCOV
125
            propsCount = Object.getOwnPropertyNames(src).length;
×
126
            metadata = Object.getOwnPropertyNames(src);
×
UNCOV
127
            if (
×
128
                objectCollapsedMaxPropsCount > 0 &&
×
129
                objectCollapsedMaxPropsCount !== true
130
            )
NEW
131
                metadata = metadata.slice(0, objectCollapsedMaxPropsCount);
×
132

UNCOV
133
            metadata = metadata.join(', ');
×
134
        }
135
        if (size === 0) {
15✔
136
            //don't render an ellipsis when an object has no items
137
            return null;
7✔
138
        } else {
139
            return (
8✔
140
                <div
141
                    {...Theme(
142
                        this.props.theme,
143
                        showMetadata ? 'ellipsis-metadata' : 'ellipsis'
8!
144
                    )}
145
                    class="node-ellipsis"
146
                    onClick={this.toggleCollapsed}
147
                >
148
                    {metadata}
149
                    {typeof objectCollapsedMaxPropsCount === 'number' &&
16!
150
                    propsCount > objectCollapsedMaxPropsCount
151
                        ? ', ...'
152
                        : ''}
153
                </div>
154
            );
155
        }
156
    };
157

158
    getObjectMetaData = src => {
46✔
159
        const { rjvId, theme } = this.props;
54✔
160
        const { size, hovered } = this.state;
54✔
161
        return (
54✔
162
            <VariableMeta rowHovered={hovered} size={size} {...this.props} />
163
        );
164
    };
165

166
    getBraceStart(object_type, expanded) {
167
        const { src, theme, iconStyle, parent_type } = this.props;
54✔
168

169
        if (parent_type === 'array_group') {
54✔
170
            return (
2✔
171
                <span>
172
                    <span {...Theme(theme, 'brace')}>
173
                        {object_type === 'array' ? '[' : '{'}
2!
174
                    </span>
175
                    {expanded ? this.getObjectMetaData(src) : null}
2!
176
                </span>
177
            );
178
        }
179

180
        const IconComponent = expanded ? ExpandedIcon : CollapsedIcon;
52✔
181

182
        return (
52✔
183
            <span>
184
                <span
185
                    onClick={e => {
UNCOV
186
                        this.toggleCollapsed();
×
187
                    }}
188
                    {...Theme(theme, 'brace-row')}
189
                >
190
                    <div
191
                        class="icon-container"
192
                        {...Theme(theme, 'icon-container')}
193
                    >
194
                        <IconComponent {...{ theme, iconStyle }} />
195
                    </div>
196
                    <ObjectName {...this.props} />
197
                    <span {...Theme(theme, 'brace')}>
198
                        {object_type === 'array' ? '[' : '{'}
52✔
199
                    </span>
200
                </span>
201
                {expanded ? this.getObjectMetaData(src) : null}
52✔
202
            </span>
203
        );
204
    }
205

206
    render() {
207
        // `indentWidth` and `collapsed` props will
208
        // perpetuate to children via `...rest`
209
        const {
210
            depth,
211
            src,
212
            namespace,
213
            name,
214
            type,
215
            parent_type,
216
            theme,
217
            jsvRoot,
218
            iconStyle,
219
            objectCollapsedMaxPropsCount,
220
            ...rest
221
        } = this.props;
54✔
222
        const { object_type, expanded } = this.state;
54✔
223

224
        let styles = {};
54✔
225
        if (!jsvRoot && parent_type !== 'array_group') {
54✔
226
            styles.paddingLeft = this.props.indentWidth * SINGLE_INDENT;
43✔
227
        } else if (parent_type === 'array_group') {
11✔
228
            styles.borderLeft = 0;
2✔
229
            styles.display = 'inline';
2✔
230
        }
231

232
        return (
54✔
233
            <div
234
                class="object-key-val"
235
                onMouseEnter={() =>
UNCOV
236
                    this.setState({ ...this.state, hovered: true })
×
237
                }
238
                onMouseLeave={() =>
UNCOV
239
                    this.setState({ ...this.state, hovered: false })
×
240
                }
241
                {...Theme(theme, jsvRoot ? 'jsv-root' : 'objectKeyVal', styles)}
54✔
242
            >
243
                {this.getBraceStart(object_type, expanded)}
244
                {expanded
54✔
245
                    ? this.getObjectContent(depth, src, {
246
                          theme,
247
                          iconStyle,
248
                          objectCollapsedMaxPropsCount,
249
                          ...rest
250
                      })
251
                    : this.getEllipsis(
252
                          parent_type,
253
                          src,
254
                          jsvRoot,
255
                          objectCollapsedMaxPropsCount
256
                      )}
257
                <span class="brace-row">
258
                    <span
259
                        style={{
260
                            ...Theme(theme, 'brace').style,
261
                            paddingLeft: expanded ? '3px' : '0px'
54✔
262
                        }}
263
                    >
264
                        {object_type === 'array' ? ']' : '}'}
54✔
265
                    </span>
266
                    {expanded ? null : this.getObjectMetaData(src)}
54✔
267
                </span>
268
            </div>
269
        );
270
    }
271

272
    renderObjectContents = (variables, props) => {
46✔
273
        const {
274
            depth,
275
            parent_type,
276
            index_offset,
277
            groupArraysAfterLength,
278
            namespace
279
        } = this.props;
39✔
280
        const { object_type } = this.state;
39✔
281
        let elements = [],
39✔
282
            variable;
283
        let keys = Object.keys(variables || {});
39!
284
        if (this.props.sortKeys && object_type !== 'array') {
39✔
285
            keys = keys.sort();
1✔
286
        }
287

288
        keys.forEach(name => {
39✔
289
            variable = new JsonVariable(name, variables[name]);
118✔
290

291
            if (parent_type === 'array_group' && index_offset) {
118✔
292
                variable.name = parseInt(variable.name) + index_offset;
2✔
293
            }
294
            if (!variables.hasOwnProperty(name)) {
118!
UNCOV
295
                return;
×
296
            } else if (variable.type === 'object') {
118✔
297
                elements.push(
12✔
298
                    <JsonObject
299
                        key={variable.name}
300
                        depth={depth + DEPTH_INCREMENT}
301
                        name={variable.name}
302
                        src={variable.value}
303
                        namespace={namespace.concat(variable.name)}
304
                        parent_type={object_type}
305
                        {...props}
306
                    />
307
                );
308
            } else if (variable.type === 'array') {
106✔
309
                let ObjectComponent = JsonObject;
13✔
310

311
                if (
13!
312
                    groupArraysAfterLength &&
23✔
313
                    variable.value.length > groupArraysAfterLength
314
                ) {
UNCOV
315
                    ObjectComponent = ArrayGroup;
×
316
                }
317

318
                elements.push(
13✔
319
                    <ObjectComponent
320
                        key={variable.name}
321
                        depth={depth + DEPTH_INCREMENT}
322
                        name={variable.name}
323
                        src={variable.value}
324
                        namespace={namespace.concat(variable.name)}
325
                        type="array"
326
                        parent_type={object_type}
327
                        {...props}
328
                    />
329
                );
330
            } else {
331
                elements.push(
93✔
332
                    <VariableEditor
333
                        key={variable.name + '_' + namespace}
334
                        variable={variable}
335
                        singleIndent={SINGLE_INDENT}
336
                        namespace={namespace}
337
                        type={this.props.type}
338
                        {...props}
339
                    />
340
                );
341
            }
342
        });
343

344
        return elements;
39✔
345
    };
346
}
347

348
//just store name, value and type with a variable
349
class JsonVariable {
350
    constructor(name, value) {
351
        this.name = name;
118✔
352
        this.value = value;
118✔
353
        this.type = toType(value);
118✔
354
    }
355
}
356

357
polyfill(RjvObject);
1✔
358

359
//export component
360
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