Skip to content

Conversation

@elisadinsmore
Copy link
Contributor

No description provided.

@codesandbox
Copy link

codesandbox bot commented Nov 17, 2022

CodeSandbox logoCodeSandbox logo  Open in CodeSandbox Web Editor | VS Code | VS Code Insiders

const removeExtraSpaces = new Sheet('removeExtraSpaces', {
departmentName: TextField({
compute: (value: any) => {
return value.replace(/\s{2,}/g, ' ')
Copy link
Contributor

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, ' ')
},
}),
})
Copy link
Contributor

@paddymul paddymul Nov 17, 2022

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

@paddymul
Copy link
Contributor

paddymul commented Nov 17, 2022

to get the full testing stuff (WIP from other branches) run the following commands

git pull
git checkout feat/simple-constraints # checkout this branch, will be setup to automatically track from remote
git checkout feat/DataHookExamples # go back to your branch
git checkout feat/simple-cosntraints -- jest.config.js src/utils/testing/SheetTester.ts # pull just those files into your branch
git commit jest.config.js src/utils/testing/SheetTester.ts -m "updated SheetTester"

run tests with
npm run test
or npm run test remove to run any testname matching remove*

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', {
Copy link
Contributor

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
Copy link
Contributor Author

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?

Comment on lines +8 to +16
(update: string) =>
(value: string): string => {
try {
return format(new Date(value), update)
} catch (err) {
return value
}
}

Copy link
Contributor

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?

Copy link
Contributor

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.

Copy link
Contributor Author

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 😆

Copy link
Contributor Author

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)
})

Copy link
Contributor Author

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)
Copy link
Contributor

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)
Copy link
Contributor

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)
})
Copy link
Contributor

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.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

expect(res).toMatchObject(expectedOutputRow)
})

test('Test set of numbers', async () => {
Copy link
Contributor

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(),
Copy link
Contributor

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
Copy link
Contributor

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
Copy link
Contributor

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 }
Copy link
Contributor

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants