Skip to content
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

[Docs]: Outdated / incomplete doc regarding async directive testing #10812

Closed
1 task done
Firokat opened this issue Jun 13, 2024 · 3 comments · Fixed by #10827
Closed
1 task done

[Docs]: Outdated / incomplete doc regarding async directive testing #10812

Firokat opened this issue Jun 13, 2024 · 3 comments · Fixed by #10827
Assignees

Comments

@Firokat
Copy link

Firokat commented Jun 13, 2024

Summary and description

The Directive documentation says to use mockAsyncRedwoodDirective to test for asynchronous directives.

As it does not seem to exist, and according to the mockRedwoodDirective docstring, I should use it instead.

/**
* @description
*
* Used for writing both synchronous and asynchronous directive tests e.g.
*
* - Transformer directives can be passed mockedResolvedValue
* - Validator directives should check for errors thrown in certain situations
* - Can provide args, directiveArgs and context to mock directive execution
*
* @example
*
* Synchronous transformer directive:
*
* ```ts
* const mockExecution = mockRedwoodDirective(myTransformer, {
* context: currentUser,
* mockedResolvedValue: 'Original Value',
* })
*
* expect(mockExecution).not.toThrow()
* expect(mockExecution()).toEqual('Transformed Value')
* ```ts
*
* @example
*
* Asynchronous transformer directive:
*
* ```ts
* const mockExecution = mockRedwoodDirective(myTransformer, {
* context: currentUser,
* mockedResolvedValue: 'Original Value',
* })
*
* await expect(mockExecution).resolves.not.toThrow()
* await expect(mockExecution()).resolves.toEqual('Transformed Value')
* ```
*/

Also, this docstring does not show how to test async validator directives, what I found to be quite troublesome.

From experimentation, I came up with this PoC to test for these.

test.ts

import {
  createValidatorDirective,
  ValidatorDirectiveFunc,
} from '@redwoodjs/graphql-server'

export const schema = gql`
  """
  Use @test to validate access to a field, query or mutation.
  """
  directive @test(truth: Boolean) on FIELD_DEFINITION
`

const validate: ValidatorDirectiveFunc = async ({ context, directiveArgs }) => {
  /**
   * Write your validation logic inside this function.
   * Validator directives do not have access to the field value, i.e. they are called before resolving the value
   *
   * - Throw an error, if you want to stop executing e.g. not sufficient permissions
   * - Validator directives can be async or sync
   * - Returned value will be ignored
   */

  // currentUser is only available when auth is setup.
  await new Promise((resolve) => setTimeout(resolve, 1000))
  if (!directiveArgs.truth) {
    throw new Error('You shall not pass!')
  }
}

const test = createValidatorDirective(schema, validate)

export default test

test.test.ts

import { getDirectiveName, mockRedwoodDirective } from '@redwoodjs/testing/api'

import test from './test'

describe('test directive', () => {
  it('declares the directive sdl as schema, with the correct name', () => {
    expect(test.schema).toBeTruthy()
    expect(getDirectiveName(test.schema)).toBe('test')
  })

  it('is true', async () => {
    const mockExecution = mockRedwoodDirective(test, {
      context: {},
      directiveArgs: { truth: true },
    })

    await expect(mockExecution()).resolves.not.toThrow()
  })

  it('is false', async () => {
    const mockExecution = mockRedwoodDirective(test, {
      context: {},
      directiveArgs: { truth: false },
    })

    await expect(mockExecution).rejects.toThrow()
  })
})

I hope this can help if anyone else has troubles with testing async validator directives and that the documentation gets clarified.

Are you interested in working on this?

  • I'm interested in working on this
@dthyresson
Copy link
Contributor

dthyresson commented Jun 14, 2024

Hi @Firokat and thanks for using directives and tests — and reporting this. I’ll have to go back as see why we had the specific async mock and when it was removed.

Your approach to resolve or reject seems sensible and depending on what I find that might be the docs update we need.

Very helpful to have the reproduction here. Thanks!

@dthyresson dthyresson self-assigned this Jun 14, 2024
@dthyresson
Copy link
Contributor

dthyresson commented Jun 14, 2024

FYI some history is here #5822
I think the implementation had the separate Async mocks and then as part of the review we elected to keep the same mock but just let it handle both. But while that was updated and the template also — the original doc update never got corrected.

So your method of testing is correct — I’ll make a docs change to clarify how to test async directives properly.

Thanks!

@Firokat
Copy link
Author

Firokat commented Jun 14, 2024

Hi, thanks for looking into this as quickly as you did !
Glad to hear that it will lead to a change to the doc.

Josh-Walker-GM added a commit that referenced this issue Jun 19, 2024
…ains how to test async directives (#10827)

Fixes #10812

This PR removes `mockAsyncRedwoodDirective` from documentation and
properly show how to test async directives using `resolves` and
`rejects`.

History:

mockAsyncRedwoodDirective was an early implementation but after PR
review it was determined that a separate functions wasn't needed, but
the resolves/rejects could be uses by making mockRedwoodDirective handle
promises better. However, the documentation retained the older
reference.

---------

Co-authored-by: Josh GM Walker <56300765+Josh-Walker-GM@users.noreply.github.com>
Josh-Walker-GM added a commit that referenced this issue Jun 25, 2024
…ains how to test async directives (#10827)

Fixes #10812

This PR removes `mockAsyncRedwoodDirective` from documentation and
properly show how to test async directives using `resolves` and
`rejects`.

History:

mockAsyncRedwoodDirective was an early implementation but after PR
review it was determined that a separate functions wasn't needed, but
the resolves/rejects could be uses by making mockRedwoodDirective handle
promises better. However, the documentation retained the older
reference.

---------

Co-authored-by: Josh GM Walker <56300765+Josh-Walker-GM@users.noreply.github.com>
Josh-Walker-GM added a commit that referenced this issue Jun 28, 2024
…ains how to test async directives (#10827)

Fixes #10812

This PR removes `mockAsyncRedwoodDirective` from documentation and
properly show how to test async directives using `resolves` and
`rejects`.

History:

mockAsyncRedwoodDirective was an early implementation but after PR
review it was determined that a separate functions wasn't needed, but
the resolves/rejects could be uses by making mockRedwoodDirective handle
promises better. However, the documentation retained the older
reference.

---------

Co-authored-by: Josh GM Walker <56300765+Josh-Walker-GM@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
2 participants