-
Notifications
You must be signed in to change notification settings - Fork 23
example data hook #52
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
|
|
| const removeExtraSpaces = new Sheet('removeExtraSpaces', { | ||
| departmentName: TextField({ | ||
| compute: (value: any) => { | ||
| return value.replace(/\s{2,}/g, ' ') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My regex is rusty, does this only remove space of two or more. maybe add a comment
| return value.replace(/\s{2,}/g, ' ') | ||
| }, | ||
| }), | ||
| }) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would like to see tests that show/verify what happens for the following string. Reason about "is this what you really want to happen"
123456789012345
" asdf"
"asdf "
" as df" - does this replace only one sequence of spaces?
"Paddy Mullen" - does this remove the single character
|
to get the full testing stuff (WIP from other branches) run the following commands
run tests with |
| import { SheetTester } from '../../../src/utils/testing/SheetTester' | ||
|
|
||
| //This hook checks for and removes special characters in a string using RegEx. | ||
| const removeSymbolsCompute = new Sheet('removeSymbolsCompute', { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would rename this to RemoveSymbolsSheet, with a sheetname of RemoveSymbolsSheet
| { | ||
| recordCompute: (record) => { | ||
| //ensuring the accountId is returned as a string | ||
| const accountNum = record.get('accountId') as string |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@paddymul I needed to ensure I was returning the accountId field as a string here otherwise TypeScript was concerned that the TPrimitive type could be a number, boolean, string, or null. Is there a better way to ensure this is a string to be able to test properly?
| (update: string) => | ||
| (value: string): string => { | ||
| try { | ||
| return format(new Date(value), update) | ||
| } catch (err) { | ||
| return value | ||
| } | ||
| } | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this code actually runs. it looks like a function that returns a function. Are you sure this is what you wanted?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oh, I see, that's waht you meant to do. Well done, you should mention this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll be honest, this is code from @hansjhoffman that I rewrote for this example so I don't know how to best explain it 😆
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is also an example that I might remove with the launch of SmartDateField, since that would cover the basically same formatting changes this is capable of handling.
| const res = await testSheet.testRecord(inputRow) | ||
| expect(res).toMatchObject(expectedOutputRow) | ||
| }) | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@paddymul this hook is waiting on the ability to test the messages that are returned, since it's a Validate hook. That's why my tests are incomplete here.
| console.log(new Date(inputRow.joinDate)) | ||
| const expectedOutputRow = { joinDate: '12/31/2020' } | ||
| const res = await testSheet.testRecord(inputRow) | ||
| expect(res).toMatchObject(expectedOutputRow) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Stylistic thing, I don't like defining the expected input and output so far apart.
Instead I would have the last lines as this
const inputRow = { joinDate: '12-31-2020' }
const expectedOutputRow = { joinDate: '12/31/2020' }
expect(res).toMatchObject(expectedOutputRow)
or even
expect( await testSheet.testRecord({joinDate:'12-31-2020' }).toMatchObject({joinDate:'12/31/2020'})
Generally for a bunch of test cases, you want the important code that differs between the cases to jump out at you, the boilerplate should fade away.
| const inputRow = { joinDate: '14 Jan 2022' } | ||
| const expectedOutputRow = { joinDate: '01/14/2022' } | ||
| const res = await testSheet.testRecord(inputRow) | ||
| expect(res).toMatchObject(expectedOutputRow) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ideally we would have a method on sheetTester so you can test an individual field, not even caring about the name of the field. so you could just say
fieldTester = new FieldTester(TextField({
compute: formatDate('MM/dd/yyyy'),
}))
expect(transformField('14 Jan 2022')).toBe('01/14/2022')
| const expectedOutputRow = { joinDate: '12242022' } | ||
| const res = await testSheet.testRecord(inputRow) | ||
| expect(res).toMatchObject(expectedOutputRow) | ||
| }) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would change your format function for this example, so that if it gets an unexpected input, it throws the error. Don't swallow errors and continue processing.
If any field hook throws an exception, the platform-sdk, will keep the original value of the field (double check the original value is kept, not the value to that point), and set a message on that cell of the error thrown.
I would rewrite your compute function so that it throws an error on unexpected input, then use testSheet.testMessage to verify you are getting the message (related to the error thrown) you expect for this field and input.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Take a look here https://github.com/FlatFilers/platform-sdk-starter/blob/main/examples/fields/SmartDateField.spec.ts#L136-L159 but make it simpler and more explicit for this field
| expect(res).toMatchObject(expectedOutputRow) | ||
| }) | ||
|
|
||
| test('Test set of numbers', async () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
please change the name. this isn't a set of numbers
| 'Test Sheet', | ||
| { | ||
| paymentStatus: TextField(), | ||
| amount: NumberField(), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Side note. we are encouraging all Fields to be called with at least an empty object {} so this becomes
NumberField({})
| amount: NumberField(), | ||
| }, | ||
| { | ||
| //because this hook is comparing multiple fields and both modifying a field and adding a message, it must be run as a recordHook rather than a fieldHook |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would recommend:
//because this hook is comparing multiple fields and both modifying a field, it must be run as a recordHook rather than a fieldHook
Adding a message at the same time shouldn't be promoted as a reason to use recordCompute... The only way you could properly set the warning message for 'payment' status is by looking at 'paymentStatus' and 'amount', that's why you want recordCompute.
| }, | ||
| { | ||
| recordCompute: (record) => { | ||
| //ensuring the accountId is returned as a string |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
because accountID is a TextField we know it will be string or possibly null. Given our existing typing implemenation, we only know that accountID could be one of null, string, number, date, boolean. Try this code instead:
//make sure we actually have a string, then continue processing
const accountID = record.get('accountID')
if(typeof accountID === 'string') { // this type guard assures typescript that we are dealing with a string
if (FIELDS['accountId'].regex.test(accountNum) === false) {
record.set('accountStatus', false)
record.addError('accountId', FIELDS.accountId.message)
} else {
record.set('accountStatus', true)
}
I would recommend explicitly handling the else case, where accountID is null.
| const testSheet = new SheetTester(TestWorkbook, 'testSheet') | ||
| test('21 Characters', async () => { | ||
| // for this inputRow | ||
| const inputRow = { accountId: '1234567890asdfghjkjhg', accountStatus: true } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These are tests that acutally need testRecord because they deal with multiple fields.
No description provided.