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

IgniteUI / igniteui-angular / 20960087204

13 Jan 2026 02:19PM UTC coverage: 12.713% (-78.8%) from 91.5%
20960087204

Pull #16746

github

web-flow
Merge 9afce6e5d into a967f087e
Pull Request #16746: fix(csv): export summaries - master

1008 of 16803 branches covered (6.0%)

19 of 23 new or added lines in 2 files covered. (82.61%)

24693 existing lines in 336 files now uncovered.

3985 of 31345 relevant lines covered (12.71%)

2.49 hits per line

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

65.08
/projects/igniteui-angular/grids/core/src/services/csv/char-separated-value-data.ts
1
import { ExportUtilities } from '../exporter-common/export-utilities';
2
import { IColumnInfo } from '../exporter-common/base-export-service';
3
import { yieldingLoop } from 'igniteui-angular/core';
4

5
/**
6
 * @hidden
7
 */
8
export class CharSeparatedValueData {
9
    private _headerRecord = '';
1✔
10
    private _dataRecords = '';
1✔
11
    private _eor = '\r\n';
1✔
12
    private _delimiter;
13
    private _escapeCharacters = ['\r', '\n', '\r\n'];
1✔
14
    private _delimiterLength = 1;
1✔
15
    private _isSpecialData = false;
1✔
16

17
    constructor(private _data: any[], valueDelimiter: string, private columns: IColumnInfo[] = [])  {
1!
18
        this.setDelimiter(valueDelimiter);
1✔
19
    }
20

21
    public prepareData(key?: any[]) {
UNCOV
22
        if (!this._data || this._data.length === 0) {
×
UNCOV
23
            return '';
×
24
        }
UNCOV
25
        let keys = [];
×
UNCOV
26
        if (key){
×
27
            keys = key;
×
28
        }else {
UNCOV
29
            keys = ExportUtilities.getKeysFromData(this._data);
×
30
        }
31

UNCOV
32
        if (keys.length === 0) {
×
33
            return '';
×
34
        }
35

UNCOV
36
        this._isSpecialData = ExportUtilities.isSpecialData(this._data[0]);
×
UNCOV
37
        this._escapeCharacters.push(this._delimiter);
×
38

UNCOV
39
        this._headerRecord = this.processHeaderRecord(keys, this._data.length);
×
UNCOV
40
        this._dataRecords = this.processDataRecords(this._data, keys);
×
41

UNCOV
42
        return this._headerRecord + this._dataRecords;
×
43
    }
44

45
    public prepareDataAsync(done: (result: string) => void, alwaysExportHeaders: boolean = true) {
×
46
        const columns = this.columns?.filter(c => !c.skip)
4✔
47
                        .sort((a, b) => a.startIndex - b.startIndex)
4✔
48
                        .sort((a, b) => a.pinnedIndex - b.pinnedIndex);
4✔
49
        const keys = columns && columns.length ? columns.map(c => c.field) : ExportUtilities.getKeysFromData(this._data);
4!
50

51
        if (this._data && this._data.length > 0) {
1✔
52
            this._isSpecialData = ExportUtilities.isSpecialData(this._data[0]);
1✔
53
        }
54
        this._escapeCharacters.push(this._delimiter);
1✔
55

56
        const headers = columns && columns.length ?
1!
57
                        columns.map(c => c.header ?? c.field) :
4!
58
                        keys;
59

60
        this._headerRecord = this.processHeaderRecord(headers, this._data.length);
1✔
61
        if (keys.length === 0 || ((!this._data || this._data.length === 0) && keys.length === 0)) {
1!
62
            // If alwaysExportHeaders is true and we have headers, export headers only
NEW
63
            if (alwaysExportHeaders && headers && headers.length > 0) {
×
NEW
64
                done(this._headerRecord);
×
65
            } else {
NEW
66
                done('');
×
67
            }
68
        } else {
69
            this.processDataRecordsAsync(this._data, keys, (dr) => {
1✔
70
                done(this._headerRecord + dr);
1✔
71
            });
72
        }
73
    }
74

75
    private processField(value, escapeChars): string {
76
        let safeValue = ExportUtilities.hasValue(value) ? String(value) : '';
92!
77
        if (escapeChars.some((v) => safeValue.includes(v))) {
368!
UNCOV
78
            safeValue = `"${safeValue}"`;
×
79
        }
80
        return safeValue + this._delimiter;
92✔
81
    }
82

83
    private processHeaderRecord(keys, dataLength): string {
84
        let recordData = '';
1✔
85
        for (const keyName of keys) {
1✔
86
            recordData += this.processField(keyName, this._escapeCharacters);
4✔
87
        }
88

89
        const result = recordData.slice(0, -this._delimiterLength);
1✔
90

91
        return dataLength > 0 ? result + this._eor : result;
1!
92
    }
93

94
    private processRecord(record, keys): string {
95
        const recordData = new Array(keys.length);
22✔
96
        for (let index = 0; index < keys.length; index++) {
22✔
97
            const value = (record[keys[index]] !== undefined) ? record[keys[index]] : this._isSpecialData ? record : '';
88!
98
            recordData[index] = this.processField(value, this._escapeCharacters);
88✔
99
        }
100

101
        return recordData.join('').slice(0, -this._delimiterLength) + this._eor;
22✔
102
    }
103

104
    private processDataRecords(currentData, keys) {
UNCOV
105
        const dataRecords = new Array(currentData.length);
×
106

UNCOV
107
        for (let i = 0; i < currentData.length; i++) {
×
UNCOV
108
            const row = currentData[i];
×
UNCOV
109
            dataRecords[i] = this.processRecord(row, keys);
×
110
        }
111

UNCOV
112
        return dataRecords.join('');
×
113
    }
114

115
    private processDataRecordsAsync(currentData, keys, done: (result: string) => void) {
116
        const dataRecords = new Array(currentData.length);
1✔
117

118
        yieldingLoop(currentData.length, 1000,
1✔
119
            (i) => {
120
                const row = currentData[i];
22✔
121
                dataRecords[i] = this.processRecord(row, keys);
22✔
122
            },
123
            () => {
124
                done(dataRecords.join(''));
1✔
125
            });
126
    }
127

128
    private setDelimiter(value) {
129
        this._delimiter = value;
1✔
130
        this._delimiterLength = value.length;
1✔
131
    }
132
}
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