mocksGraphqlPlugin.js 3.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. // Copyright (C) 2012-2024 Zammad Foundation, https://zammad-foundation.org/
  2. /* eslint-disable no-nested-ternary */
  3. /* eslint-disable @typescript-eslint/no-require-imports */
  4. const { basename } = require('path')
  5. const { convertFactory } = require('@graphql-codegen/visitor-plugin-common')
  6. const camelCase = require('lodash/camelCase.js')
  7. const startCase = require('lodash/startCase.js')
  8. /* eslint-enable @typescript-eslint/no-require-imports */
  9. /** @typedef {import('graphql').OperationDefinitionNode} OperationDefinitionNode */
  10. const pascalCase = (str) => startCase(camelCase(str))
  11. const getCompositionFunctionSuffix = (name, operationType) => {
  12. if (
  13. name.includes('Query') ||
  14. name.includes('Mutation') ||
  15. name.includes('Subscription')
  16. ) {
  17. return ''
  18. }
  19. return pascalCase(operationType)
  20. }
  21. const getOperationSuffix = (config, node, operationType) => {
  22. const { omitOperationSuffix = false, dedupeOperationSuffix = false } = config
  23. const operationName =
  24. typeof node === 'string' ? node : node.name ? node.name.value : ''
  25. return omitOperationSuffix
  26. ? ''
  27. : dedupeOperationSuffix &&
  28. operationName.toLowerCase().endsWith(operationType.toLowerCase())
  29. ? ''
  30. : operationType
  31. }
  32. module.exports.plugin = (schema, documents, config) => {
  33. // we assume that there is only one operation per file
  34. // if not, then we take the first operation and assume it is the only one
  35. const node = documents[0].document.definitions[0]
  36. const suffix = getCompositionFunctionSuffix(node.name.value, node.operation)
  37. const convertName = convertFactory(config)
  38. const operationName = convertName(node.name.value, {
  39. suffix,
  40. useTypesPrefix: false,
  41. })
  42. const baseFile = basename(documents[0].location).replace(
  43. /\.graphql$/,
  44. '.api.ts',
  45. )
  46. const documentVariableName = convertName(node, {
  47. suffix: config.documentVariableSuffix || 'Document',
  48. prefix: config.documentVariablePrefix,
  49. useTypesPrefix: false,
  50. })
  51. const operationType = pascalCase(node.operation)
  52. const operationTypeSuffix = getOperationSuffix(config, node, operationType)
  53. const operationResultType = `Types.${convertName(node, {
  54. suffix: operationTypeSuffix,
  55. })}`
  56. const operationVariablesTypes = `Types.${convertName(node, {
  57. suffix: `${operationTypeSuffix}Variables`,
  58. })}`
  59. return {
  60. prepend: [
  61. "import * as Mocks from '#tests/graphql/builders/mocks.ts'",
  62. `import * as Operations from './${baseFile}'`,
  63. ],
  64. content: [
  65. node.operation === 'subscription'
  66. ? `
  67. export function get${operationName}Handler() {
  68. return Mocks.getGraphQLSubscriptionHandler<${operationResultType}>(Operations.${documentVariableName})
  69. }
  70. `
  71. : `
  72. export function mock${operationName}(defaults: Mocks.MockDefaultsValue<${operationResultType}, ${operationVariablesTypes}>) {
  73. return Mocks.mockGraphQLResult(Operations.${documentVariableName}, defaults)
  74. }
  75. export function waitFor${operationName}Calls() {
  76. return Mocks.waitForGraphQLMockCalls<${operationResultType}>(Operations.${documentVariableName})
  77. }
  78. `,
  79. ],
  80. }
  81. }