Skip to content

Commit 2c9fa91

Browse files
committed
Added StringBuilder class and tests
1 parent 482081a commit 2c9fa91

File tree

4 files changed

+296
-0
lines changed

4 files changed

+296
-0
lines changed
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
/**
2+
* Defines a builder for constructing a string from values.
3+
*/
4+
export class StringBuilder {
5+
private _strings: string[];
6+
7+
/**
8+
* Initializes a new instance of the StringBuilder class with an optional starting string value.
9+
* @param value The optional starting string value.
10+
*/
11+
constructor(value: string | StringBuilder | null = null) {
12+
this._strings = [];
13+
this.append(value);
14+
}
15+
16+
/**
17+
* Appends the value to this instance.
18+
* @param value The value to append.
19+
* @returns {StringBuilder} A reference to this instance after the append operation has completed.
20+
*/
21+
public append(value: string | StringBuilder | null): StringBuilder {
22+
if (value === undefined || value === null) {
23+
return this;
24+
}
25+
26+
if (value instanceof StringBuilder) {
27+
this._strings.push(...value._strings);
28+
} else {
29+
if (/^\s*$/.test(value)) {
30+
return this;
31+
}
32+
33+
this._strings.push(value);
34+
}
35+
36+
return this;
37+
}
38+
39+
/**
40+
* Inserts the value to this instance at the specified index.
41+
* @param index The position in this instance where the value should be inserted.
42+
* @param value The value to insert.
43+
* @returns {StringBuilder} A reference to this instance after the insert operation has completed.
44+
*/
45+
public insert(index: number, value: string | StringBuilder | null): StringBuilder {
46+
if (value === undefined || value === null) {
47+
return this;
48+
}
49+
50+
if (value instanceof StringBuilder) {
51+
this._strings.splice(index, 0, ...value._strings);
52+
} else {
53+
if (/^\s*$/.test(value)) {
54+
return this;
55+
}
56+
57+
this._strings.splice(index, 0, value);
58+
}
59+
60+
return this;
61+
}
62+
63+
/**
64+
* Replaces all occurrences of a specified string or value based on a regular expression in this instance with another specified string.
65+
* @param search The string or regular expression to find values to replace.
66+
* @param replace The string to replace values with.
67+
* @returns {StringBuilder} A reference to this instance after the replace operation has completed.
68+
*/
69+
public replace(search: string | RegExp, replace: string): StringBuilder {
70+
for (let i = 0; i < this._strings.length; i++) {
71+
this._strings[i] = this._strings[i].replace(search, replace);
72+
}
73+
74+
return this;
75+
}
76+
77+
/**
78+
* Removes the specified range of characters from this instance.
79+
* @param startIndex The zero-based position in this instance where removal begins.
80+
* @param length The number of characters to remove.
81+
* @returns {StringBuilder} A reference to this instance after the remove operation has completed.
82+
*/
83+
public remove(startIndex: number, length: number): void {
84+
this._strings.splice(startIndex, length);
85+
}
86+
87+
/**
88+
* Checks whether this instance is empty.
89+
* @returns {boolean} True if this instance is empty; otherwise, false.
90+
*/
91+
public isEmpty(): boolean {
92+
return this._strings.length === 0;
93+
}
94+
95+
/**
96+
* Clears all strings from this instance.
97+
*/
98+
public clear(): void {
99+
this._strings = [];
100+
}
101+
102+
/**
103+
* Returns a string representation of the value of this instance with a join.
104+
* @returns {string} The strings with a join.
105+
*/
106+
public toString(join: string): string {
107+
return this._strings.join(join);
108+
}
109+
}

MADE.Runtime/src/Text/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export * from './StringBuilder'

MADE.Runtime/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
1+
export * from "./Text";
12
export * from "./Guid";
23
export * from "./IEquatable";
Lines changed: 185 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,185 @@
1+
import { StringBuilder } from '../../src'
2+
3+
describe("when appending a value", () => {
4+
it("should accept a string value", () => {
5+
// Arrange
6+
const builder = new StringBuilder();
7+
8+
// Act
9+
builder.append("Hello");
10+
11+
// Assert
12+
expect(builder.toString(" ")).toBe("Hello");
13+
});
14+
15+
it("should accept a populated StringBuilder", () => {
16+
// Arrange
17+
const builder = new StringBuilder();
18+
builder.append("Hello");
19+
20+
const otherBuilder = new StringBuilder();
21+
22+
// Act
23+
otherBuilder.append(builder);
24+
25+
// Assert
26+
expect(otherBuilder.toString(" ")).toBe("Hello");
27+
});
28+
29+
it("should not add a null value", () => {
30+
// Arrange
31+
const builder = new StringBuilder();
32+
33+
// Act
34+
builder.append(null);
35+
36+
// Assert
37+
expect(builder.toString(" ")).toBe("");
38+
});
39+
40+
it("should not add an empty string", () => {
41+
// Arrange
42+
const builder = new StringBuilder();
43+
44+
// Act
45+
builder.append("");
46+
47+
// Assert
48+
expect(builder.toString(" ")).toBe("");
49+
});
50+
});
51+
52+
describe("when inserting a value", () => {
53+
it("should accept a string value", () => {
54+
// Arrange
55+
const builder = new StringBuilder();
56+
builder.append("World");
57+
58+
// Act
59+
builder.insert(0, "Hello");
60+
61+
// Assert
62+
expect(builder.toString(" ")).toBe("Hello World");
63+
});
64+
65+
it("should accept a populated StringBuilder", () => {
66+
// Arrange
67+
const builder = new StringBuilder();
68+
builder.append("Hello");
69+
70+
const otherBuilder = new StringBuilder();
71+
otherBuilder.append("World");
72+
73+
// Act
74+
otherBuilder.insert(0, builder);
75+
76+
// Assert
77+
expect(otherBuilder.toString(" ")).toBe("Hello World");
78+
});
79+
80+
it("should not insert a null value", () => {
81+
// Arrange
82+
const builder = new StringBuilder();
83+
builder.append("World");
84+
85+
// Act
86+
builder.insert(0, null);
87+
88+
// Assert
89+
expect(builder.toString(" ")).toBe("World");
90+
});
91+
92+
it("should not insert an empty string", () => {
93+
// Arrange
94+
const builder = new StringBuilder();
95+
builder.append("World");
96+
97+
// Act
98+
builder.insert(0, "");
99+
100+
// Assert
101+
expect(builder.toString(" ")).toBe("World");
102+
});
103+
});
104+
105+
describe("when replacing a value", () => {
106+
it("should replace by a string", () => {
107+
// Arrange
108+
const builder = new StringBuilder();
109+
builder.append("World");
110+
111+
// Act
112+
builder.replace("World", "Hello");
113+
114+
// Assert
115+
expect(builder.toString(" ")).toBe("Hello");
116+
});
117+
118+
it("should replace by a regular expression", () => {
119+
// Arrange
120+
const builder = new StringBuilder();
121+
builder.append("World");
122+
123+
// Act
124+
builder.replace(/World/g, "Hello");
125+
126+
// Assert
127+
expect(builder.toString(" ")).toBe("Hello");
128+
});
129+
});
130+
131+
describe("when removing by range", () => {
132+
it("should remove items in range", () => {
133+
// Arrange
134+
const builder = new StringBuilder();
135+
builder.append("Hello");
136+
builder.append("Digital");
137+
builder.append("World");
138+
139+
// Act
140+
builder.remove(1, 1);
141+
142+
// Assert
143+
expect(builder.toString(" ")).toBe("Hello World");
144+
});
145+
});
146+
147+
describe("when checking is empty", () => {
148+
it("should return true if empty", () => {
149+
// Arrange
150+
const builder = new StringBuilder();
151+
152+
// Act
153+
const result = builder.isEmpty();
154+
155+
// Assert
156+
expect(result).toBe(true);
157+
});
158+
159+
it("should return false if populated", () => {
160+
// Arrange
161+
const builder = new StringBuilder();
162+
builder.append("Hello");
163+
164+
// Act
165+
const result = builder.isEmpty();
166+
167+
// Assert
168+
expect(result).toBe(false);
169+
});
170+
});
171+
172+
describe("when clearing", () => {
173+
it("should be empty", () => {
174+
// Arrange
175+
const builder = new StringBuilder();
176+
builder.append("Hello");
177+
builder.append("World");
178+
179+
// Act
180+
builder.clear();
181+
182+
// Assert
183+
expect(builder.isEmpty()).toBe(true);
184+
});
185+
});

0 commit comments

Comments
 (0)