Skip to content

Commit

Permalink
feat: shortcut methods for the ResultValue helper
Browse files Browse the repository at this point in the history
  • Loading branch information
danielo515 committed Dec 28, 2023
1 parent 5859363 commit 00ba405
Show file tree
Hide file tree
Showing 3 changed files with 214 additions and 0 deletions.
25 changes: 25 additions & 0 deletions docs/ResultValue.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,3 +89,28 @@ The above code will print the list field as a bullet list, but all the values wi

The map method takes a function that takes the value and returns a new value.
It can be used when none of the provided printing are enough for your use case, or when one of them is almost what you need but you need to transform the value a bit more.


### `trimmed`,`lower`,`upper` shortcuts

The ResultValue class provides some shortcuts to common transformations of the value.
They are:
- `trimmed`: Trims the value, removing any leading or trailing whitespace.
- `lower`: Converts the value to lowercase.
- `upper`: Converts the value to uppercase.

All of these shortcuts return a new ResultValue object, so you can chain them with other methods.

```typescript
<% result.getValue('listField').trimmed.upper.bullets %>
```

The above code will print the list field as a bullet list, but all the values will be uppercased and trimmed.
You can chain as many or as little as you want.
The most common use is probably just to use one of them, like `trimmed` or `upper`.

```typescript
<% result.getValue('myField').trimmed %>
```

All of this shortcuts are able to handle single values and lists, so you can use them with any value.
153 changes: 153 additions & 0 deletions src/core/ResultValue.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -148,4 +148,157 @@ describe("ResultValue", () => {
expect(bulletList).toEqual("");
});
});
describe("upper", () => {
it("should convert the value to uppercase", () => {
// Arrange
const value = "test";
const resultValue = ResultValue.from(value, "Test");

// Act
const upper = resultValue.upper;

// Assert
expect(upper.toString()).toEqual("TEST");
});
it("should convert an array of values to uppercase", () => {
// Arrange
const value = ["foo", "bar"];
const resultValue = ResultValue.from(value, "Test");

// Act
const upper = resultValue.upper;

// Assert
expect(upper.toString()).toEqual("FOO, BAR");
});
it('upper strings and numbers mixed', () => {
// Arrange
const value = ["foo", 42];
const resultValue = ResultValue.from(value, "Test");

// Act
const upper = resultValue.upper;

// Assert
expect(upper.bullets).toEqual('- FOO\n- 42');
})
it('upper should be chainable', () => {
// Arrange
const value = "test";
const resultValue = ResultValue.from(value, "Test");

// Act
const upper = resultValue.upper.upper;

// Assert
expect(upper.toString()).toEqual("TEST");
});
});
describe("lower", () => {
it("should convert the value to lowercase", () => {
// Arrange
const value = "TEST";
const resultValue = ResultValue.from(value, "Test");

// Act
const lower = resultValue.lower;

// Assert
expect(lower.toString()).toEqual("test");
});
it("should convert an array of values to lowercase", () => {
// Arrange
const value = ["FOO", "BAR"];
const resultValue = ResultValue.from(value, "Test");

// Act
const lower = resultValue.lower;

// Assert
expect(lower.toString()).toEqual("foo, bar");
});
it('lower strings and numbers mixed', () => {
// Arrange
const value = ["FOO", 42];
const resultValue = ResultValue.from(value, "Test");

// Act
const lower = resultValue.lower;

// Assert
expect(lower.bullets).toEqual('- foo\n- 42');
})
it('lower should be chainable', () => {
// Arrange
const value = "TEST";
const resultValue = ResultValue.from(value, "Test");

// Act
const lower = resultValue.lower.lower;

// Assert
expect(lower.toString()).toEqual("test");
});
});
describe("trimmed", () => {
it("should trim the value", () => {
// Arrange
const value = " test ";
const resultValue = ResultValue.from(value, "Test");

// Act
const trimmed = resultValue.trimmed;

// Assert
expect(trimmed.toString()).toEqual("test");
});
it("should trim an array of values", () => {
// Arrange
const value = [" foo ", " bar "];
const resultValue = ResultValue.from(value, "Test");

// Act
const trimmed = resultValue.trimmed;

// Assert
expect(trimmed.toString()).toEqual("foo, bar");
});
it('trimmed strings and numbers mixed', () => {
// Arrange
const value = [" foo ", 42];
const resultValue = ResultValue.from(value, "Test");

// Act
const trimmed = resultValue.trimmed;

// Assert
expect(trimmed.bullets).toEqual('- foo\n- 42');
})
it('trimmed should be chainable', () => {
// Arrange
const value = " test ";
const resultValue = ResultValue.from(value, "Test");
// Act
const trimmed = resultValue.trimmed.trimmed;
// Assert
expect(trimmed.toString()).toEqual("test");
});
})
describe("chaining shortcuts", () => {
it("should be possible to chain upper, lower and trim", () => {
// Arrange
const value = " TeSt ";
const resultValue = ResultValue.from(value, "Test");
// Act
const trimmed = resultValue.trimmed.upper.lower;
// Assert
expect(trimmed.toString()).toEqual("test");
});
it('should be possible to chain shortcuts with other format methods', () => {
const value = [" TeSt ", 'foo ', 55];
const resultValue = ResultValue.from(value, "Test");
const final = resultValue.trimmed.upper.lower;
expect(final.bullets).toEqual('- test\n- foo\n- 55');
});
});
});
36 changes: 36 additions & 0 deletions src/core/ResultValue.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,18 @@ function isRecord(value: unknown): value is Record<string, unknown> {
return typeof value === "object" && value !== null && !Array.isArray(value);
}

function deepMap(value: unknown, fn: (value: unknown) => unknown): unknown {
if (Array.isArray(value)) {
return value.map((v) => deepMap(v, fn));
}
if (isRecord(value)) {
return Object.fromEntries(
Object.entries(value).map(([key, value]) => [key, deepMap(value, fn)]),
);
}
return fn(value);
}

type Reporter = (title: string) => (message: string) => void;
/**
* class representing a single form value.
Expand Down Expand Up @@ -141,4 +153,28 @@ export class ResultValue<T = unknown> {
get bullets() {
return this.toBulletList();
}

/**
* getter that returns all the string values uppercased.
* If the value is an array, it will return an array with all the strings uppercased.
*/
get upper() {
return this.map((v) => deepMap(v, (it) => typeof it === "string" ? it.toLocaleUpperCase() : it));
}
/**
* getter that returns all the string values lowercased.
* If the value is an array, it will return an array with all the strings lowercased.
* If the value is an object, it will return an object with all the string values lowercased.
* @returns FormValue
*/
get lower() {
return this.map((v) => deepMap(v, (it) => typeof it === "string" ? it.toLocaleLowerCase() : it));
}
/**
* getter that returns all the string values trimmed.
* */
get trimmed() {
return this.map((v) => deepMap(v, (it) => typeof it === "string" ? it.trim() : it));
}

}

0 comments on commit 00ba405

Please sign in to comment.