Skip to content

Commit 2a85dc3

Browse files
Merge pull request #52 from mrjones2014/main
Add ResultRecord#doesNotHaveErrors and ResultRecord#getErrorMessageFor
2 parents 3b28f32 + 8e2ba60 commit 2a85dc3

2 files changed

Lines changed: 126 additions & 16 deletions

File tree

src/view-models/result-record.test.ts

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ import { ResultRecord } from "./result-record";
22
import { ErrorType } from "../enumerations/error-type";
33
import { ResultErrorRecord } from "./result-error-record";
44
import { ResultError } from "../interfaces/result-error";
5+
import { Factory } from "rosie";
6+
import { FactoryType } from "../tests/factories/factory-type";
57

68
describe("ResultRecord", () => {
79
// -----------------------------------------------------------------------------------------
@@ -203,6 +205,97 @@ describe("ResultRecord", () => {
203205

204206
// #endregion errorCount
205207

208+
// -----------------------------------------------------------------------------------------
209+
// #region doesNotHaveErrors
210+
// -----------------------------------------------------------------------------------------
211+
212+
describe("doesNotHaveErrors", () => {
213+
test("when errors is null, returns true", () => {
214+
expect(
215+
Factory.build<ResultRecord<any>>(FactoryType.ResultRecord, {
216+
errors: (null as unknown) as any[],
217+
}).doesNotHaveErrors()
218+
).toBeTrue();
219+
});
220+
221+
test("when errors is undefined, returns true", () => {
222+
expect(
223+
Factory.build<ResultRecord<any>>(FactoryType.ResultRecord, {
224+
errors: undefined,
225+
}).doesNotHaveErrors()
226+
).toBeTrue();
227+
});
228+
229+
test("when errors is empty array, returns true", () => {
230+
expect(
231+
Factory.build<ResultRecord<any>>(FactoryType.ResultRecord, {
232+
errors: [],
233+
}).doesNotHaveErrors()
234+
).toBeTrue();
235+
});
236+
237+
test("when errors is not empty, returns false", () => {
238+
// Arrange
239+
const errors = [
240+
Factory.build<ResultErrorRecord>(FactoryType.ResultErrorRecord),
241+
];
242+
243+
// Act & Assert
244+
expect(
245+
Factory.build<ResultRecord<any>>(FactoryType.ResultRecord, {
246+
errors: errors,
247+
}).doesNotHaveErrors()
248+
).toBeFalse();
249+
});
250+
}); // end doesNotHaveErrors
251+
252+
// -----------------------------------------------------------------------------------------
253+
// #region getErrorMessageFor
254+
// -----------------------------------------------------------------------------------------
255+
256+
describe("#getErrorMessageFor", () => {
257+
it("When no error exists for given key, then returns undefined", () => {
258+
// Arrange
259+
const errorKey = "TEST_ERROR_KEY";
260+
const resultRecord = Factory.build<ResultRecord<any>>(
261+
FactoryType.ResultRecord,
262+
{
263+
errors: [],
264+
}
265+
);
266+
267+
// Act
268+
const result = resultRecord.getErrorMessageFor(errorKey);
269+
270+
// Assert
271+
expect(result).toBeNil();
272+
});
273+
274+
it("When an error exists for the given key, then returns the error message", () => {
275+
// Arrange
276+
const errorKey = "TEST_ERROR_KEY";
277+
const resultRecord = Factory.build<ResultRecord<any>>(
278+
FactoryType.ResultRecord,
279+
{
280+
errors: [
281+
Factory.build<ResultErrorRecord>(
282+
FactoryType.ResultErrorRecord,
283+
{
284+
key: errorKey,
285+
}
286+
),
287+
],
288+
}
289+
);
290+
291+
// Act
292+
const result = resultRecord.getErrorMessageFor(errorKey);
293+
294+
// Assert
295+
expect(result).not.toBeNil();
296+
});
297+
}); // end getErrorMessageFor
298+
206299
// -----------------------------------------------------------------------------------------
207300
// #region hasErrorFor
208301
// -----------------------------------------------------------------------------------------

src/view-models/result-record.ts

Lines changed: 33 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { Record } from "immutable";
33
import { ResultErrorRecord } from "./result-error-record";
44
import { Result } from "../interfaces/result";
55
import { ErrorType } from "../enumerations/error-type";
6+
import { RecordUtils } from "../utilities/record-utils";
67

78
const defaultValues: Result<any> = {
89
errors: undefined,
@@ -19,15 +20,13 @@ class ResultRecord<T> extends Record(defaultValues) implements Result<T> {
1920

2021
constructor(params?: Result<T>) {
2122
if (params == null) {
22-
params = {};
23+
params = Object.assign(defaultValues, params);
2324
}
2425

2526
if (CollectionUtils.hasValues(params.errors)) {
2627
const errors = params.errors as any[];
2728
params.errors = errors.map((error) =>
28-
error instanceof ResultErrorRecord
29-
? error
30-
: new ResultErrorRecord(error)
29+
RecordUtils.ensureRecord(error, ResultErrorRecord)
3130
);
3231
}
3332

@@ -60,27 +59,44 @@ class ResultRecord<T> extends Record(defaultValues) implements Result<T> {
6059
return this._addErrorByType(key, message, ErrorType.ValidationError);
6160
}
6261

62+
/**
63+
* Evaluates whether there are any errors on the result
64+
*/
65+
public doesNotHaveErrors(): boolean {
66+
return !this.hasErrors();
67+
}
68+
6369
/**
6470
* Returns total number of errors
6571
*/
6672
public errorCount(): number {
67-
if (this.errors == null) {
73+
if (this.doesNotHaveErrors()) {
6874
return 0;
6975
}
7076

71-
return CollectionUtils.hasValues(this.errors) ? this.errors.length : 0;
77+
return this.errors!.length;
7278
}
7379

7480
/**
75-
* Determines if the result contains an error for the supplied key
76-
* @param key error key for which to search
81+
* Returns an error message for a given key
82+
* @param key
7783
*/
78-
public hasErrorFor(key: string): boolean {
79-
if (this.errors == null || !this.hasErrors()) {
84+
public getErrorMessageFor(key: string): string | undefined {
85+
return this.errors?.find((e) => e.key === key)?.message;
86+
}
87+
88+
/**
89+
* Determines if the result contains an error for the supplied key(s)
90+
* @param keys error keys for which to search
91+
*/
92+
public hasErrorFor(...keys: string[]): boolean {
93+
if (this.doesNotHaveErrors()) {
8094
return false;
8195
}
8296

83-
return this.errors.some((e) => e.key === key);
97+
return this.errors!.some((error: ResultErrorRecord) =>
98+
keys.some((key: string) => key === error.key)
99+
);
84100
}
85101

86102
/**
@@ -94,7 +110,7 @@ class ResultRecord<T> extends Record(defaultValues) implements Result<T> {
94110
* Map all errors into simple string array
95111
*/
96112
public listErrors(): string[] {
97-
if (!this.hasErrors()) {
113+
if (this.doesNotHaveErrors()) {
98114
return [];
99115
}
100116
const errors = this.errors as ResultErrorRecord[];
@@ -105,9 +121,10 @@ class ResultRecord<T> extends Record(defaultValues) implements Result<T> {
105121
* Map all error messages into a simple string array.
106122
*/
107123
public listErrorMessages(): string[] {
108-
if (!this.hasErrors()) {
124+
if (this.doesNotHaveErrors()) {
109125
return [];
110126
}
127+
111128
const errors = this.errors as ResultErrorRecord[];
112129
return errors
113130
.map((e) => String(e.message) || "")
@@ -118,7 +135,7 @@ class ResultRecord<T> extends Record(defaultValues) implements Result<T> {
118135
* Merges new values into the record and returns a new instance.
119136
*
120137
* @param {Partial<Result<T>>} values
121-
* @returns {ResultRecord}
138+
* @returns {ResultRecord<T>}
122139
* @memberof ResultRecord
123140
*/
124141
public with(values: Partial<Result<T>>): ResultRecord<T> {
@@ -153,9 +170,9 @@ class ResultRecord<T> extends Record(defaultValues) implements Result<T> {
153170
}
154171

155172
// -----------------------------------------------------------------------------------------
156-
// #region Export
173+
// #region Exports
157174
// -----------------------------------------------------------------------------------------
158175

159176
export { ResultRecord };
160177

161-
// #endregion Export
178+
// #endregion Exports

0 commit comments

Comments
 (0)