dce-reactkit 3.4.0-beta.8 → 3.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eslintrc.js +0 -2
- package/dist/cjs/index.js +190 -36371
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/types/helpers/abbreviate.test.d.ts +5 -0
- package/dist/cjs/types/helpers/avg.test.d.ts +5 -0
- package/dist/cjs/types/helpers/canReviewLogs.d.ts +5 -0
- package/dist/cjs/types/helpers/canReviewLogs.test.d.ts +5 -0
- package/dist/cjs/types/helpers/ceilToNumDecimals.test.d.ts +5 -0
- package/dist/cjs/types/helpers/compareArraysByProp.test.d.ts +5 -0
- package/dist/cjs/types/helpers/extractProp.test.d.ts +5 -0
- package/dist/cjs/types/helpers/floorToNumDecimals.test.d.ts +5 -0
- package/dist/cjs/types/helpers/forceNumIntoBounds.test.d.ts +5 -0
- package/dist/cjs/types/helpers/genCSV.test.d.ts +5 -0
- package/dist/cjs/types/helpers/genCommaList.d.ts +12 -0
- package/dist/cjs/types/helpers/genCommaList.test.d.ts +1 -0
- package/dist/cjs/types/helpers/getHumanReadableDate.test.d.ts +5 -0
- package/dist/cjs/types/helpers/getLocalTimeInfo.test.d.ts +6 -0
- package/dist/cjs/types/helpers/getMonthName.test.d.ts +5 -0
- package/dist/cjs/types/helpers/getOrdinal.test.d.ts +5 -0
- package/dist/cjs/types/helpers/getPartOfDay.test.d.ts +5 -0
- package/dist/cjs/types/helpers/getTimeInfoInET.test.d.ts +5 -0
- package/dist/cjs/types/helpers/validators/shared/constants/ERROR_MESSAGES.d.ts +10 -0
- package/dist/cjs/types/helpers/validators/shared/helpers/validateRegex.d.ts +19 -0
- package/dist/cjs/types/helpers/validators/shared/types/ValidationResult.d.ts +12 -0
- package/dist/cjs/types/helpers/validators/validateEmail.d.ts +11 -0
- package/dist/cjs/types/helpers/validators/validateEmail.test.d.ts +1 -0
- package/dist/cjs/types/helpers/validators/validatePhoneNumber.d.ts +11 -0
- package/dist/cjs/types/helpers/validators/validatePhoneNumber.test.d.ts +1 -0
- package/dist/cjs/types/helpers/validators/validateString.d.ts +22 -0
- package/dist/cjs/types/helpers/validators/validateString.test.d.ts +1 -0
- package/dist/cjs/types/index.d.ts +1 -6
- package/dist/esm/index.js +419 -36579
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/types/helpers/abbreviate.test.d.ts +5 -0
- package/dist/esm/types/helpers/avg.test.d.ts +5 -0
- package/dist/esm/types/helpers/canReviewLogs.d.ts +5 -0
- package/dist/esm/types/helpers/canReviewLogs.test.d.ts +5 -0
- package/dist/esm/types/helpers/ceilToNumDecimals.test.d.ts +5 -0
- package/dist/esm/types/helpers/compareArraysByProp.test.d.ts +5 -0
- package/dist/esm/types/helpers/extractProp.test.d.ts +5 -0
- package/dist/esm/types/helpers/floorToNumDecimals.test.d.ts +5 -0
- package/dist/esm/types/helpers/forceNumIntoBounds.test.d.ts +5 -0
- package/dist/esm/types/helpers/genCSV.test.d.ts +5 -0
- package/dist/esm/types/helpers/genCommaList.d.ts +12 -0
- package/dist/esm/types/helpers/genCommaList.test.d.ts +1 -0
- package/dist/esm/types/helpers/getHumanReadableDate.test.d.ts +5 -0
- package/dist/esm/types/helpers/getLocalTimeInfo.test.d.ts +6 -0
- package/dist/esm/types/helpers/getMonthName.test.d.ts +5 -0
- package/dist/esm/types/helpers/getOrdinal.test.d.ts +5 -0
- package/dist/esm/types/helpers/getPartOfDay.test.d.ts +5 -0
- package/dist/esm/types/helpers/getTimeInfoInET.test.d.ts +5 -0
- package/dist/esm/types/helpers/validators/shared/constants/ERROR_MESSAGES.d.ts +10 -0
- package/dist/esm/types/helpers/validators/shared/helpers/validateRegex.d.ts +19 -0
- package/dist/esm/types/helpers/validators/shared/types/ValidationResult.d.ts +12 -0
- package/dist/esm/types/helpers/validators/validateEmail.d.ts +11 -0
- package/dist/esm/types/helpers/validators/validateEmail.test.d.ts +1 -0
- package/dist/esm/types/helpers/validators/validatePhoneNumber.d.ts +11 -0
- package/dist/esm/types/helpers/validators/validatePhoneNumber.test.d.ts +1 -0
- package/dist/esm/types/helpers/validators/validateString.d.ts +22 -0
- package/dist/esm/types/helpers/validators/validateString.test.d.ts +1 -0
- package/dist/esm/types/index.d.ts +1 -6
- package/dist/index.d.ts +35 -166
- package/package.json +13 -17
- package/src/client/initClient.tsx +20 -12
- package/src/components/AppWrapper.tsx +1 -1
- package/src/components/ItemPicker/index.test.tsx +10 -10
- package/src/helpers/abbreviate.test.ts +26 -0
- package/src/helpers/avg.test.ts +24 -0
- package/src/helpers/canReviewLogs.test.ts +67 -0
- package/src/helpers/canReviewLogs.ts +20 -0
- package/src/helpers/ceilToNumDecimals.test.ts +39 -0
- package/src/helpers/compareArraysByProp.test.ts +102 -0
- package/src/helpers/extractProp.test.ts +34 -0
- package/src/helpers/floorToNumDecimals.test.ts +39 -0
- package/src/helpers/forceNumIntoBounds.test.ts +34 -0
- package/src/helpers/genCSV.test.ts +61 -0
- package/src/helpers/genCSV.ts +5 -2
- package/src/helpers/genCommaList.test.ts +57 -0
- package/src/helpers/genCommaList.ts +21 -0
- package/src/helpers/getHumanReadableDate.test.ts +29 -0
- package/src/helpers/getLocalTimeInfo.test.ts +48 -0
- package/src/helpers/getMonthName.test.ts +79 -0
- package/src/helpers/getOrdinal.test.ts +84 -0
- package/src/helpers/{getOrdinal.tsx → getOrdinal.ts} +1 -0
- package/src/helpers/getPartOfDay.test.ts +56 -0
- package/src/helpers/getTimeInfoInET.test.ts +72 -0
- package/src/helpers/validators/shared/constants/ERROR_MESSAGES.ts +18 -0
- package/src/helpers/validators/shared/helpers/validateRegex.ts +47 -0
- package/src/helpers/validators/shared/types/ValidationResult.ts +20 -0
- package/src/helpers/validators/validateEmail.test.ts +110 -0
- package/src/helpers/validators/validateEmail.ts +47 -0
- package/src/helpers/validators/validatePhoneNumber.test.ts +94 -0
- package/src/helpers/validators/validatePhoneNumber.ts +49 -0
- package/src/helpers/validators/validateString.test.ts +175 -0
- package/src/helpers/validators/validateString.ts +171 -0
- package/src/index.ts +10 -12
- package/tsconfig.json +6 -2
- package/dist/cjs/types/components/DBEntryManagerPanel/AddOrEditDBEntry/CreatableMultiselect.d.ts +0 -10
- package/dist/cjs/types/components/DBEntryManagerPanel/AddOrEditDBEntry/index.d.ts +0 -34
- package/dist/cjs/types/components/DBEntryManagerPanel/helpers/generateEndpointPath.d.ts +0 -9
- package/dist/cjs/types/components/DBEntryManagerPanel/index.d.ts +0 -25
- package/dist/cjs/types/components/DBEntryManagerPanel/types/DBEntry.d.ts +0 -8
- package/dist/cjs/types/components/DBEntryManagerPanel/types/DBEntryField.d.ts +0 -49
- package/dist/cjs/types/components/DBEntryManagerPanel/types/DBEntryFieldType.d.ts +0 -12
- package/dist/cjs/types/helpers/addDBEditorEndpoints.d.ts +0 -40
- package/dist/esm/types/components/DBEntryManagerPanel/AddOrEditDBEntry/CreatableMultiselect.d.ts +0 -10
- package/dist/esm/types/components/DBEntryManagerPanel/AddOrEditDBEntry/index.d.ts +0 -34
- package/dist/esm/types/components/DBEntryManagerPanel/helpers/generateEndpointPath.d.ts +0 -9
- package/dist/esm/types/components/DBEntryManagerPanel/index.d.ts +0 -25
- package/dist/esm/types/components/DBEntryManagerPanel/types/DBEntry.d.ts +0 -8
- package/dist/esm/types/components/DBEntryManagerPanel/types/DBEntryField.d.ts +0 -49
- package/dist/esm/types/components/DBEntryManagerPanel/types/DBEntryFieldType.d.ts +0 -12
- package/dist/esm/types/helpers/addDBEditorEndpoints.d.ts +0 -40
- package/src/components/DBEntryManagerPanel/AddOrEditDBEntry/CreatableMultiselect.tsx +0 -286
- package/src/components/DBEntryManagerPanel/AddOrEditDBEntry/index.tsx +0 -722
- package/src/components/DBEntryManagerPanel/helpers/generateEndpointPath.ts +0 -15
- package/src/components/DBEntryManagerPanel/index.tsx +0 -511
- package/src/components/DBEntryManagerPanel/types/DBEntry.ts +0 -7
- package/src/components/DBEntryManagerPanel/types/DBEntryField.ts +0 -94
- package/src/components/DBEntryManagerPanel/types/DBEntryFieldType.ts +0 -18
- package/src/helpers/addDBEditorEndpoints.ts +0 -124
- /package/src/helpers/{abbreviate.tsx → abbreviate.ts} +0 -0
- /package/src/helpers/{avg.tsx → avg.ts} +0 -0
- /package/src/helpers/{ceilToNumDecimals.tsx → ceilToNumDecimals.ts} +0 -0
- /package/src/helpers/{floorToNumDecimals.tsx → floorToNumDecimals.ts} +0 -0
- /package/src/helpers/{forceNumIntoBounds.tsx → forceNumIntoBounds.ts} +0 -0
- /package/src/helpers/{getLocalTimeInfo.tsx → getLocalTimeInfo.ts} +0 -0
- /package/src/helpers/{getTimeInfoInET.tsx → getTimeInfoInET.ts} +0 -0
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unit tests for canReviewLogs
|
|
3
|
+
* @author Gabe Abrams
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
// Import dce-reactkit
|
|
7
|
+
import stubServerEndpoint from './stubServerEndpoint';
|
|
8
|
+
|
|
9
|
+
// Import main function
|
|
10
|
+
import canReviewLogs, { resetCanReviewCache } from './canReviewLogs';
|
|
11
|
+
|
|
12
|
+
// Import shared constants
|
|
13
|
+
import LOG_REVIEW_STATUS_ROUTE from '../constants/LOG_REVIEW_STATUS_ROUTE';
|
|
14
|
+
|
|
15
|
+
describe('helpers > canReviewLogs', () => {
|
|
16
|
+
beforeEach(() => {
|
|
17
|
+
// Reset the cache
|
|
18
|
+
resetCanReviewCache();
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
it('should return true if the server returns a truthy value', async () => {
|
|
22
|
+
stubServerEndpoint({
|
|
23
|
+
method: 'GET',
|
|
24
|
+
path: LOG_REVIEW_STATUS_ROUTE,
|
|
25
|
+
body: true,
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
const result = await canReviewLogs();
|
|
29
|
+
expect(result).toEqual(true);
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
it('should return false if the server returns a falsy value', async () => {
|
|
33
|
+
stubServerEndpoint({
|
|
34
|
+
method: 'GET',
|
|
35
|
+
path: LOG_REVIEW_STATUS_ROUTE,
|
|
36
|
+
body: false,
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
const result = await canReviewLogs();
|
|
40
|
+
expect(result).toEqual(false);
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
it('should return false if the server throws an error', async () => {
|
|
44
|
+
stubServerEndpoint({
|
|
45
|
+
method: 'GET',
|
|
46
|
+
path: LOG_REVIEW_STATUS_ROUTE,
|
|
47
|
+
errorMessage: 'Server error',
|
|
48
|
+
errorCode: 'C500',
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
const result = await canReviewLogs();
|
|
52
|
+
expect(result).toEqual(false);
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
it('should cache the server response and return it on subsequent calls', async () => {
|
|
56
|
+
stubServerEndpoint({
|
|
57
|
+
method: 'GET',
|
|
58
|
+
path: LOG_REVIEW_STATUS_ROUTE,
|
|
59
|
+
body: true,
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
const result1 = await canReviewLogs();
|
|
63
|
+
const result2 = await canReviewLogs();
|
|
64
|
+
expect(result1).toEqual(true);
|
|
65
|
+
expect(result2).toEqual(true);
|
|
66
|
+
});
|
|
67
|
+
});
|
|
@@ -4,9 +4,29 @@ import visitServerEndpoint from './visitServerEndpoint';
|
|
|
4
4
|
// Import shared constants
|
|
5
5
|
import LOG_REVIEW_STATUS_ROUTE from '../constants/LOG_REVIEW_STATUS_ROUTE';
|
|
6
6
|
|
|
7
|
+
/*------------------------------------------------------------------------*/
|
|
8
|
+
/* -------------------------------- Cache ------------------------------- */
|
|
9
|
+
/*------------------------------------------------------------------------*/
|
|
10
|
+
|
|
7
11
|
// Cache user's ability
|
|
8
12
|
let canReview: boolean | undefined = undefined;
|
|
9
13
|
|
|
14
|
+
/*------------------------------------------------------------------------*/
|
|
15
|
+
/* ---------------------------- Other Helpers --------------------------- */
|
|
16
|
+
/*------------------------------------------------------------------------*/
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Reset the cached version of canReview
|
|
20
|
+
* @author Gabe Abrams
|
|
21
|
+
*/
|
|
22
|
+
export const resetCanReviewCache = () => {
|
|
23
|
+
canReview = undefined;
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
/*------------------------------------------------------------------------*/
|
|
27
|
+
/* -------------------------------- Main -------------------------------- */
|
|
28
|
+
/*------------------------------------------------------------------------*/
|
|
29
|
+
|
|
10
30
|
/**
|
|
11
31
|
* Check if the current user can review logs
|
|
12
32
|
* @author Gabe Abrams
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Test file for the ceilToNumDecimals helper
|
|
3
|
+
* @author Gabe Abrams
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
// Import main function
|
|
7
|
+
import ceilToNumDecimals from './ceilToNumDecimals';
|
|
8
|
+
|
|
9
|
+
describe('ceilToNumDecimals', () => {
|
|
10
|
+
it('should return 0 for 0 with 0 decimals', () => {
|
|
11
|
+
const result = ceilToNumDecimals(0, 0);
|
|
12
|
+
expect(result).toEqual(0);
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
it('should return 1 for 1 with 0 decimals', () => {
|
|
16
|
+
const result = ceilToNumDecimals(1, 0);
|
|
17
|
+
expect(result).toEqual(1);
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
it('should return 1.24 for 1.234 with 2 decimals', () => {
|
|
21
|
+
const result = ceilToNumDecimals(1.234, 2);
|
|
22
|
+
expect(result).toEqual(1.24);
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
it('should return -1.23 for -1.234 with 2 decimals', () => {
|
|
26
|
+
const result = ceilToNumDecimals(-1.234, 2);
|
|
27
|
+
expect(result).toEqual(-1.23);
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
it('should return 1234 for 1234 with 0 decimals', () => {
|
|
31
|
+
const result = ceilToNumDecimals(1234, 0);
|
|
32
|
+
expect(result).toEqual(1234);
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
it('should return 0.002 for 0.00123 with 3 decimals', () => {
|
|
36
|
+
const result = ceilToNumDecimals(0.00123, 3);
|
|
37
|
+
expect(result).toEqual(0.002);
|
|
38
|
+
});
|
|
39
|
+
});
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Test file for the compareArraysByProp helper
|
|
3
|
+
* @author Gabe Abrams
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
// Import main helper
|
|
7
|
+
import compareArraysByProp from './compareArraysByProp';
|
|
8
|
+
|
|
9
|
+
describe('compareArraysByProp', () => {
|
|
10
|
+
it('should return true for two empty arrays', () => {
|
|
11
|
+
const result = compareArraysByProp([], [], 'id');
|
|
12
|
+
expect(result).toEqual(true);
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
it('should return true for two arrays with the same objects in the same order', () => {
|
|
16
|
+
const a = [{ id: 1, name: 'Alice' }, { id: 2, name: 'Bob' }, { id: 3, name: 'Charlie' }];
|
|
17
|
+
const b = [{ id: 1, name: 'Alice' }, { id: 2, name: 'Bob' }, { id: 3, name: 'Charlie' }];
|
|
18
|
+
const result = compareArraysByProp(a, b, 'id');
|
|
19
|
+
expect(result).toEqual(true);
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
it('should return true for two arrays with the same objects in a different order', () => {
|
|
23
|
+
const a = [{ id: 1, name: 'Alice' }, { id: 2, name: 'Bob' }, { id: 3, name: 'Charlie' }];
|
|
24
|
+
const b = [{ id: 3, name: 'Charlie' }, { id: 1, name: 'Alice' }, { id: 2, name: 'Bob' }];
|
|
25
|
+
const result = compareArraysByProp(a, b, 'id');
|
|
26
|
+
expect(result).toEqual(true);
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
it('should return false for two arrays with different objects', () => {
|
|
30
|
+
const a = [{ id: 1, name: 'Alice' }, { id: 2, name: 'Bob' }, { id: 3, name: 'Charlie' }];
|
|
31
|
+
const b = [{ id: 4, name: 'Dave' }, { id: 5, name: 'Eve' }, { id: 6, name: 'Frank' }];
|
|
32
|
+
const result = compareArraysByProp(a, b, 'id');
|
|
33
|
+
expect(result).toEqual(false);
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
it('should return false for two arrays with different objects and some shared objects', () => {
|
|
37
|
+
const a = [{ id: 1, name: 'Alice' }, { id: 2, name: 'Bob' }, { id: 3, name: 'Charlie' }];
|
|
38
|
+
const b = [{ id: 2, name: 'Bob' }, { id: 3, name: 'Charlie' }, { id: 4, name: 'Dave' }];
|
|
39
|
+
const result = compareArraysByProp(a, b, 'id');
|
|
40
|
+
expect(result).toEqual(false);
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
it('should return true for two arrays with the same objects with multiple properties', () => {
|
|
44
|
+
const a = [
|
|
45
|
+
{ id: 1, name: 'Alice', age: 25 },
|
|
46
|
+
{ id: 2, name: 'Bob', age: 30 },
|
|
47
|
+
{ id: 3, name: 'Charlie', age: 35 },
|
|
48
|
+
];
|
|
49
|
+
const b = [
|
|
50
|
+
{ id: 1, name: 'Alice', age: 25 },
|
|
51
|
+
{ id: 2, name: 'Bob', age: 30 },
|
|
52
|
+
{ id: 3, name: 'Charlie', age: 35 },
|
|
53
|
+
];
|
|
54
|
+
const result = compareArraysByProp(a, b, 'id');
|
|
55
|
+
expect(result).toEqual(true);
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
it('should return true for two arrays with the same objects with multiple properties in a different order', () => {
|
|
59
|
+
const a = [
|
|
60
|
+
{ id: 1, name: 'Alice', age: 25 },
|
|
61
|
+
{ id: 2, name: 'Bob', age: 30 },
|
|
62
|
+
{ id: 3, name: 'Charlie', age: 35 },
|
|
63
|
+
];
|
|
64
|
+
const b = [
|
|
65
|
+
{ id: 3, name: 'Charlie', age: 35 },
|
|
66
|
+
{ id: 1, name: 'Alice', age: 25 },
|
|
67
|
+
{ id: 2, name: 'Bob', age: 30 },
|
|
68
|
+
];
|
|
69
|
+
const result = compareArraysByProp(a, b, 'id');
|
|
70
|
+
expect(result).toEqual(true);
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
it('should return false for two arrays with different objects with multiple properties', () => {
|
|
74
|
+
const a = [
|
|
75
|
+
{ id: 1, name: 'Alice', age: 25 },
|
|
76
|
+
{ id: 2, name: 'Bob', age: 30 },
|
|
77
|
+
{ id: 3, name: 'Charlie', age: 35 },
|
|
78
|
+
];
|
|
79
|
+
const b = [
|
|
80
|
+
{ id: 4, name: 'Dave', age: 40 },
|
|
81
|
+
{ id: 5, name: 'Eve', age: 45 },
|
|
82
|
+
{ id: 6, name: 'Frank', age: 50 },
|
|
83
|
+
];
|
|
84
|
+
const result = compareArraysByProp(a, b, 'id');
|
|
85
|
+
expect(result).toEqual(false);
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
it('should return false for two arrays with different objects with multiple properties and some shared objects', () => {
|
|
89
|
+
const a = [
|
|
90
|
+
{ id: 1, name: 'Alice', age: 25 },
|
|
91
|
+
{ id: 2, name: 'Bob', age: 30 },
|
|
92
|
+
{ id: 3, name: 'Charlie', age: 35 },
|
|
93
|
+
];
|
|
94
|
+
const b = [
|
|
95
|
+
{ id: 2, name: 'Bob', age: 30 },
|
|
96
|
+
{ id: 3, name: 'Charlie', age: 35 },
|
|
97
|
+
{ id: 4, name: 'Dave', age: 40 },
|
|
98
|
+
];
|
|
99
|
+
const result = compareArraysByProp(a, b, 'id');
|
|
100
|
+
expect(result).toEqual(false);
|
|
101
|
+
});
|
|
102
|
+
});
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Test file for the extractProp helper
|
|
3
|
+
* @author Gabe Abrams
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
// Import main helper
|
|
7
|
+
import extractProp from './extractProp';
|
|
8
|
+
|
|
9
|
+
describe('extractProp', () => {
|
|
10
|
+
it('should return an empty array if the input array is empty', () => {
|
|
11
|
+
const result = extractProp([], 'age');
|
|
12
|
+
expect(result).toEqual([]);
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
it('should extract the correct property from each object in the array', () => {
|
|
16
|
+
const users = [
|
|
17
|
+
{ name: 'Alice', age: 25 },
|
|
18
|
+
{ name: 'Bob', age: 30 },
|
|
19
|
+
{ name: 'Charlie', age: 35 },
|
|
20
|
+
];
|
|
21
|
+
const result = extractProp(users, 'age');
|
|
22
|
+
expect(result).toEqual([25, 30, 35]);
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
it('should return undefined for objects that do not have the specified property', () => {
|
|
26
|
+
const users = [
|
|
27
|
+
{ name: 'Alice', age: 25 },
|
|
28
|
+
{ name: 'Bob' },
|
|
29
|
+
{ name: 'Charlie', age: 35 },
|
|
30
|
+
];
|
|
31
|
+
const result = extractProp(users, 'age');
|
|
32
|
+
expect(result).toEqual([25, undefined, 35]);
|
|
33
|
+
});
|
|
34
|
+
});
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Test file for the floorToNumDecimals helper
|
|
3
|
+
* @author Gabe Abrams
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
// Import main function
|
|
7
|
+
import floorToNumDecimals from './floorToNumDecimals';
|
|
8
|
+
|
|
9
|
+
describe('floorToNumDecimals', () => {
|
|
10
|
+
it('should return 0 for 0 with 0 decimals', () => {
|
|
11
|
+
const result = floorToNumDecimals(0, 0);
|
|
12
|
+
expect(result).toEqual(0);
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
it('should return 1 for 1 with 0 decimals', () => {
|
|
16
|
+
const result = floorToNumDecimals(1, 0);
|
|
17
|
+
expect(result).toEqual(1);
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
it('should return 1.23 for 1.234 with 2 decimals', () => {
|
|
21
|
+
const result = floorToNumDecimals(1.234, 2);
|
|
22
|
+
expect(result).toEqual(1.23);
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
it('should return -1.24 for -1.234 with 2 decimals', () => {
|
|
26
|
+
const result = floorToNumDecimals(-1.234, 2);
|
|
27
|
+
expect(result).toEqual(-1.24);
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
it('should return 1234 for 1234 with 0 decimals', () => {
|
|
31
|
+
const result = floorToNumDecimals(1234, 0);
|
|
32
|
+
expect(result).toEqual(1234);
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
it('should return 0.001 for 0.00123 with 3 decimals', () => {
|
|
36
|
+
const result = floorToNumDecimals(0.00123, 3);
|
|
37
|
+
expect(result).toEqual(0.001);
|
|
38
|
+
});
|
|
39
|
+
});
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Test file for the forceNumIntoBounds helper
|
|
3
|
+
* @author Gabe Abrams
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
// Import main helper
|
|
7
|
+
import forceNumIntoBounds from './forceNumIntoBounds';
|
|
8
|
+
|
|
9
|
+
describe('forceNumIntoBounds', () => {
|
|
10
|
+
it('should return the number if it is within the bounds', () => {
|
|
11
|
+
const result = forceNumIntoBounds(5, 0, 10);
|
|
12
|
+
expect(result).toEqual(5);
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
it('should return the minimum bound if the number is less than the minimum', () => {
|
|
16
|
+
const result = forceNumIntoBounds(-5, 0, 10);
|
|
17
|
+
expect(result).toEqual(0);
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
it('should return the maximum bound if the number is greater than the maximum', () => {
|
|
21
|
+
const result = forceNumIntoBounds(15, 0, 10);
|
|
22
|
+
expect(result).toEqual(10);
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
it('should return the minimum bound if the number is equal to the minimum', () => {
|
|
26
|
+
const result = forceNumIntoBounds(0, 0, 10);
|
|
27
|
+
expect(result).toEqual(0);
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
it('should return the maximum bound if the number is equal to the maximum', () => {
|
|
31
|
+
const result = forceNumIntoBounds(10, 0, 10);
|
|
32
|
+
expect(result).toEqual(10);
|
|
33
|
+
});
|
|
34
|
+
});
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Test file for the genCSV helper
|
|
3
|
+
* @author Gabe Abrams
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
// Import main helper
|
|
7
|
+
import genCSV from './genCSV';
|
|
8
|
+
|
|
9
|
+
describe('genCSV', () => {
|
|
10
|
+
it('should return an empty string for empty data', () => {
|
|
11
|
+
const result = genCSV([], []);
|
|
12
|
+
expect(result).toEqual('');
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
it('should generate a CSV with the correct headers and data', () => {
|
|
16
|
+
const columns = [
|
|
17
|
+
{ title: 'Name', param: 'name' },
|
|
18
|
+
{ title: 'Age', param: 'age' },
|
|
19
|
+
{ title: 'Email', param: 'email' },
|
|
20
|
+
];
|
|
21
|
+
const data = [
|
|
22
|
+
{ name: 'Alice', age: 25, email: 'alice@example.com' },
|
|
23
|
+
{ name: 'Bob', age: 30, email: 'bob@example.com' },
|
|
24
|
+
{ name: 'Charlie', age: 35, email: 'charlie@example.com' },
|
|
25
|
+
];
|
|
26
|
+
const expected = `Name,Age,Email\nAlice,25,alice@example.com\nBob,30,bob@example.com\nCharlie,35,charlie@example.com`;
|
|
27
|
+
const result = genCSV(data, columns);
|
|
28
|
+
expect(result).toEqual(expected);
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
it('should handle undefined and null values correctly', () => {
|
|
32
|
+
const columns = [
|
|
33
|
+
{ title: 'Name', param: 'name' },
|
|
34
|
+
{ title: 'Age', param: 'age' },
|
|
35
|
+
{ title: 'Email', param: 'email' },
|
|
36
|
+
];
|
|
37
|
+
const data = [
|
|
38
|
+
{ name: 'Alice', age: undefined, email: null },
|
|
39
|
+
{ name: 'Bob', age: null, email: 'bob@example.com' },
|
|
40
|
+
{ name: 'Charlie', age: 35, email: undefined },
|
|
41
|
+
];
|
|
42
|
+
const expected = `Name,Age,Email\nAlice,,\nBob,,bob@example.com\nCharlie,35,`;
|
|
43
|
+
const result = genCSV(data, columns);
|
|
44
|
+
expect(result).toEqual(expected);
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
it('should handle objects in cells correctly', () => {
|
|
48
|
+
const columns = [
|
|
49
|
+
{ title: 'Name', param: 'name' },
|
|
50
|
+
{ title: 'Data', param: 'data' },
|
|
51
|
+
];
|
|
52
|
+
const data = [
|
|
53
|
+
{ name: 'Alice', data: { foo: 'bar' } },
|
|
54
|
+
{ name: 'Bob', data: [1, 2, 3] },
|
|
55
|
+
{ name: 'Charlie', data: null },
|
|
56
|
+
];
|
|
57
|
+
const expected = `Name,Data\nAlice,"{""foo"":""bar""}"\nBob,"[1,2,3]"\nCharlie,`;
|
|
58
|
+
const result = genCSV(data, columns);
|
|
59
|
+
expect(result).toEqual(expected);
|
|
60
|
+
});
|
|
61
|
+
});
|
package/src/helpers/genCSV.ts
CHANGED
|
@@ -5,13 +5,16 @@
|
|
|
5
5
|
* @returns escaped cell text
|
|
6
6
|
*/
|
|
7
7
|
const escapeCellText = (text: string): string => {
|
|
8
|
-
if (
|
|
8
|
+
if (
|
|
9
|
+
!String(text).includes(',')
|
|
10
|
+
&& !String(text).includes('"')
|
|
11
|
+
) {
|
|
9
12
|
// No need to escape
|
|
10
13
|
return String(text);
|
|
11
14
|
}
|
|
12
15
|
|
|
13
16
|
// Perform escape
|
|
14
|
-
return `"${String(text).replace(/"/g, '""')}`;
|
|
17
|
+
return `"${String(text).replace(/"/g, '""')}"`;
|
|
15
18
|
};
|
|
16
19
|
|
|
17
20
|
/**
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
// Import function
|
|
2
|
+
import genCommaList from './genCommaList';
|
|
3
|
+
|
|
4
|
+
test(
|
|
5
|
+
'Empty list.',
|
|
6
|
+
async () => {
|
|
7
|
+
const emptyList: string[] = [];
|
|
8
|
+
const emptyListResponse: string = '';
|
|
9
|
+
|
|
10
|
+
const result = genCommaList(emptyList);
|
|
11
|
+
expect(result).toStrictEqual(emptyListResponse);
|
|
12
|
+
},
|
|
13
|
+
);
|
|
14
|
+
|
|
15
|
+
test(
|
|
16
|
+
'One word list.',
|
|
17
|
+
async () => {
|
|
18
|
+
const oneList: string[] = ['apples'];
|
|
19
|
+
const oneListResponse: string = 'apples';
|
|
20
|
+
|
|
21
|
+
const result = genCommaList(oneList);
|
|
22
|
+
expect(result).toStrictEqual(oneListResponse);
|
|
23
|
+
},
|
|
24
|
+
);
|
|
25
|
+
|
|
26
|
+
test(
|
|
27
|
+
'Two word list.',
|
|
28
|
+
async () => {
|
|
29
|
+
const twoList: string[] = ['apples', 'oranges'];
|
|
30
|
+
const twoListResponse: string = 'apples and oranges';
|
|
31
|
+
|
|
32
|
+
const result = genCommaList(twoList);
|
|
33
|
+
expect(result).toStrictEqual(twoListResponse);
|
|
34
|
+
},
|
|
35
|
+
);
|
|
36
|
+
|
|
37
|
+
test(
|
|
38
|
+
'Three word list.',
|
|
39
|
+
async () => {
|
|
40
|
+
const threeList: string[] = ['apples', 'oranges', 'bananas'];
|
|
41
|
+
const threeListResponse: string = 'apples, oranges, and bananas';
|
|
42
|
+
|
|
43
|
+
const result = genCommaList(threeList);
|
|
44
|
+
expect(result).toStrictEqual(threeListResponse);
|
|
45
|
+
},
|
|
46
|
+
);
|
|
47
|
+
|
|
48
|
+
test(
|
|
49
|
+
'Four word list.',
|
|
50
|
+
async () => {
|
|
51
|
+
const fourList: string[] = ['apples', 'oranges', 'bananas', 'grapes'];
|
|
52
|
+
const fourListResponse: string = 'apples, oranges, bananas, and grapes';
|
|
53
|
+
|
|
54
|
+
const result = genCommaList(fourList);
|
|
55
|
+
expect(result).toStrictEqual(fourListResponse);
|
|
56
|
+
},
|
|
57
|
+
);
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Given an array of strings, create a single comma-separated string that includes
|
|
3
|
+
* 'and' as well as an oxford comma.
|
|
4
|
+
* Ex: ['apples'] => 'apples'
|
|
5
|
+
* Ex: ['apples', 'bananas'] => 'apples and bananas'
|
|
6
|
+
* Ex: ['apples', 'bananas', 'grapes'] => 'apples, bananas, and grapes'
|
|
7
|
+
* @author Austen Money
|
|
8
|
+
* @param list an array of elements to be made into a single comma-separated string.
|
|
9
|
+
* @returns a comma-separated string.
|
|
10
|
+
*/
|
|
11
|
+
const genCommaList = (list: string[]): string => {
|
|
12
|
+
const { length } = list;
|
|
13
|
+
|
|
14
|
+
return (
|
|
15
|
+
length < 2
|
|
16
|
+
? list.join('')
|
|
17
|
+
: `${list.slice(0, length - 1).join(', ')}${length < 3 ? ' and ' : ', and '}${list[length - 1]}`
|
|
18
|
+
);
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export default genCommaList;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Test file for the getHumanReadableDate helper
|
|
3
|
+
* @author Gabe Abrams
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
// Import helpers
|
|
7
|
+
import getHumanReadableDate from './getHumanReadableDate';
|
|
8
|
+
import getOrdinal from './getOrdinal';
|
|
9
|
+
|
|
10
|
+
describe('getHumanReadableDate', () => {
|
|
11
|
+
it('should return the current date if no argument is passed', () => {
|
|
12
|
+
const result = getHumanReadableDate();
|
|
13
|
+
const now = new Date();
|
|
14
|
+
const expected = `${now.toLocaleString('default', { month: 'short' })} ${now.getDate()}${getOrdinal(now.getDate())}`;
|
|
15
|
+
expect(result).toEqual(expected);
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
it('should return the correct date for a given timestamp', () => {
|
|
19
|
+
const timestamp = 1629822000000; // 2021-08-24T12:20:00.000Z
|
|
20
|
+
const result = getHumanReadableDate(timestamp);
|
|
21
|
+
expect(result).toEqual('Aug 24th 2021');
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
it('should return the correct date for a given Date object', () => {
|
|
25
|
+
const date = new Date('2021-08-24T12:20:00.000Z');
|
|
26
|
+
const result = getHumanReadableDate(date);
|
|
27
|
+
expect(result).toEqual('Aug 24th 2021');
|
|
28
|
+
});
|
|
29
|
+
});
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Test for getLocalTimeInfo helper function
|
|
3
|
+
* NOTE: only works if this test is run on a machine in ET
|
|
4
|
+
* @author Gabe Abrams
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
// Import main function
|
|
8
|
+
import getLocalTimeInfo from './getLocalTimeInfo';
|
|
9
|
+
|
|
10
|
+
describe('getLocalTimeInfo', () => {
|
|
11
|
+
it('should return current time info if no argument is passed', () => {
|
|
12
|
+
const result = getLocalTimeInfo();
|
|
13
|
+
const now = new Date();
|
|
14
|
+
expect(result.timestamp).toBeCloseTo(now.getTime(), -3);
|
|
15
|
+
expect(result.year).toEqual(now.getFullYear());
|
|
16
|
+
expect(result.month).toEqual(now.getMonth() + 1);
|
|
17
|
+
expect(result.day).toEqual(now.getDate());
|
|
18
|
+
expect(result.hour).toEqual(now.getHours());
|
|
19
|
+
expect(result.minute).toEqual(now.getMinutes());
|
|
20
|
+
expect(result.isPM).toEqual(now.getHours() >= 12);
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
it('should return correct time info for a given timestamp', () => {
|
|
24
|
+
const timestamp = 1629822000000; // 2021-08-24T12:20:00.000Z
|
|
25
|
+
const result = getLocalTimeInfo(timestamp);
|
|
26
|
+
expect(result.timestamp).toEqual(timestamp);
|
|
27
|
+
expect(result.year).toEqual(2021);
|
|
28
|
+
expect(result.month).toEqual(8);
|
|
29
|
+
expect(result.day).toEqual(24);
|
|
30
|
+
expect(result.hour).toEqual(12);
|
|
31
|
+
expect(result.hour12).toEqual(12);
|
|
32
|
+
expect(result.minute).toEqual(20);
|
|
33
|
+
expect(result.isPM).toEqual(true);
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
it('should return correct time info for a given Date object', () => {
|
|
37
|
+
const date = new Date('2021-08-24T12:20:00.000Z');
|
|
38
|
+
const result = getLocalTimeInfo(date);
|
|
39
|
+
expect(result.timestamp).toEqual(date.getTime());
|
|
40
|
+
expect(result.year).toEqual(2021);
|
|
41
|
+
expect(result.month).toEqual(8);
|
|
42
|
+
expect(result.day).toEqual(24);
|
|
43
|
+
expect(result.hour).toEqual(8);
|
|
44
|
+
expect(result.hour12).toEqual(8);
|
|
45
|
+
expect(result.minute).toEqual(20);
|
|
46
|
+
expect(result.isPM).toEqual(false);
|
|
47
|
+
});
|
|
48
|
+
});
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Test for getMonthName helper
|
|
3
|
+
* @author Gabe Abrams
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
// Import main helper
|
|
7
|
+
import getMonthName from './getMonthName';
|
|
8
|
+
|
|
9
|
+
describe('getMonthName', () => {
|
|
10
|
+
it('should return January for 1', () => {
|
|
11
|
+
const result = getMonthName(1);
|
|
12
|
+
expect(result).toEqual({ short: 'Jan', full: 'January' });
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
it('should return February for 2', () => {
|
|
16
|
+
const result = getMonthName(2);
|
|
17
|
+
expect(result).toEqual({ short: 'Feb', full: 'February' });
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
it('should return March for 3', () => {
|
|
21
|
+
const result = getMonthName(3);
|
|
22
|
+
expect(result).toEqual({ short: 'Mar', full: 'March' });
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
it('should return April for 4', () => {
|
|
26
|
+
const result = getMonthName(4);
|
|
27
|
+
expect(result).toEqual({ short: 'Apr', full: 'April' });
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
it('should return May for 5', () => {
|
|
31
|
+
const result = getMonthName(5);
|
|
32
|
+
expect(result).toEqual({ short: 'May', full: 'May' });
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
it('should return June for 6', () => {
|
|
36
|
+
const result = getMonthName(6);
|
|
37
|
+
expect(result).toEqual({ short: 'Jun', full: 'June' });
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
it('should return July for 7', () => {
|
|
41
|
+
const result = getMonthName(7);
|
|
42
|
+
expect(result).toEqual({ short: 'Jul', full: 'July' });
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
it('should return August for 8', () => {
|
|
46
|
+
const result = getMonthName(8);
|
|
47
|
+
expect(result).toEqual({ short: 'Aug', full: 'August' });
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
it('should return September for 9', () => {
|
|
51
|
+
const result = getMonthName(9);
|
|
52
|
+
expect(result).toEqual({ short: 'Sep', full: 'September' });
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
it('should return October for 10', () => {
|
|
56
|
+
const result = getMonthName(10);
|
|
57
|
+
expect(result).toEqual({ short: 'Oct', full: 'October' });
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
it('should return November for 11', () => {
|
|
61
|
+
const result = getMonthName(11);
|
|
62
|
+
expect(result).toEqual({ short: 'Nov', full: 'November' });
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
it('should return December for 12', () => {
|
|
66
|
+
const result = getMonthName(12);
|
|
67
|
+
expect(result).toEqual({ short: 'Dec', full: 'December' });
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
it('should return January for 0', () => {
|
|
71
|
+
const result = getMonthName(0);
|
|
72
|
+
expect(result).toEqual({ short: 'Jan', full: 'January' });
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
it('should return January for 13', () => {
|
|
76
|
+
const result = getMonthName(13);
|
|
77
|
+
expect(result).toEqual({ short: 'Jan', full: 'January' });
|
|
78
|
+
});
|
|
79
|
+
});
|