您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

plugin-tool-workflow-error.test.tsx 6.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  1. /**
  2. * Test cases to reproduce the plugin tool workflow error
  3. * Issue: #23154 - Application error when loading plugin tools in workflow
  4. * Root cause: split() operation called on null/undefined values
  5. */
  6. describe('Plugin Tool Workflow Error Reproduction', () => {
  7. /**
  8. * Mock function to simulate the problematic code in switch-plugin-version.tsx:29
  9. * const [pluginId] = uniqueIdentifier.split(':')
  10. */
  11. const mockSwitchPluginVersionLogic = (uniqueIdentifier: string | null | undefined) => {
  12. // This directly reproduces the problematic line from switch-plugin-version.tsx:29
  13. const [pluginId] = uniqueIdentifier!.split(':')
  14. return pluginId
  15. }
  16. /**
  17. * Test case 1: Simulate null uniqueIdentifier
  18. * This should reproduce the error mentioned in the issue
  19. */
  20. it('should reproduce error when uniqueIdentifier is null', () => {
  21. expect(() => {
  22. mockSwitchPluginVersionLogic(null)
  23. }).toThrow('Cannot read properties of null (reading \'split\')')
  24. })
  25. /**
  26. * Test case 2: Simulate undefined uniqueIdentifier
  27. */
  28. it('should reproduce error when uniqueIdentifier is undefined', () => {
  29. expect(() => {
  30. mockSwitchPluginVersionLogic(undefined)
  31. }).toThrow('Cannot read properties of undefined (reading \'split\')')
  32. })
  33. /**
  34. * Test case 3: Simulate empty string uniqueIdentifier
  35. */
  36. it('should handle empty string uniqueIdentifier', () => {
  37. expect(() => {
  38. const result = mockSwitchPluginVersionLogic('')
  39. expect(result).toBe('') // Empty string split by ':' returns ['']
  40. }).not.toThrow()
  41. })
  42. /**
  43. * Test case 4: Simulate malformed uniqueIdentifier without colon separator
  44. */
  45. it('should handle malformed uniqueIdentifier without colon separator', () => {
  46. expect(() => {
  47. const result = mockSwitchPluginVersionLogic('malformed-identifier-without-colon')
  48. expect(result).toBe('malformed-identifier-without-colon') // No colon means full string returned
  49. }).not.toThrow()
  50. })
  51. /**
  52. * Test case 5: Simulate valid uniqueIdentifier
  53. */
  54. it('should work correctly with valid uniqueIdentifier', () => {
  55. expect(() => {
  56. const result = mockSwitchPluginVersionLogic('valid-plugin-id:1.0.0')
  57. expect(result).toBe('valid-plugin-id')
  58. }).not.toThrow()
  59. })
  60. })
  61. /**
  62. * Test for the variable processing split error in use-single-run-form-params
  63. */
  64. describe('Variable Processing Split Error', () => {
  65. /**
  66. * Mock function to simulate the problematic code in use-single-run-form-params.ts:91
  67. * const getDependentVars = () => {
  68. * return varInputs.map(item => item.variable.slice(1, -1).split('.'))
  69. * }
  70. */
  71. const mockGetDependentVars = (varInputs: Array<{ variable: string | null | undefined }>) => {
  72. return varInputs.map((item) => {
  73. // Guard against null/undefined variable to prevent app crash
  74. if (!item.variable || typeof item.variable !== 'string')
  75. return []
  76. return item.variable.slice(1, -1).split('.')
  77. }).filter(arr => arr.length > 0) // Filter out empty arrays
  78. }
  79. /**
  80. * Test case 1: Variable processing with null variable
  81. */
  82. it('should handle null variable safely', () => {
  83. const varInputs = [{ variable: null }]
  84. expect(() => {
  85. mockGetDependentVars(varInputs)
  86. }).not.toThrow()
  87. const result = mockGetDependentVars(varInputs)
  88. expect(result).toEqual([]) // null variables are filtered out
  89. })
  90. /**
  91. * Test case 2: Variable processing with undefined variable
  92. */
  93. it('should handle undefined variable safely', () => {
  94. const varInputs = [{ variable: undefined }]
  95. expect(() => {
  96. mockGetDependentVars(varInputs)
  97. }).not.toThrow()
  98. const result = mockGetDependentVars(varInputs)
  99. expect(result).toEqual([]) // undefined variables are filtered out
  100. })
  101. /**
  102. * Test case 3: Variable processing with empty string
  103. */
  104. it('should handle empty string variable', () => {
  105. const varInputs = [{ variable: '' }]
  106. expect(() => {
  107. mockGetDependentVars(varInputs)
  108. }).not.toThrow()
  109. const result = mockGetDependentVars(varInputs)
  110. expect(result).toEqual([]) // Empty string is filtered out, so result is empty array
  111. })
  112. /**
  113. * Test case 4: Variable processing with valid variable format
  114. */
  115. it('should work correctly with valid variable format', () => {
  116. const varInputs = [{ variable: '{{workflow.node.output}}' }]
  117. expect(() => {
  118. mockGetDependentVars(varInputs)
  119. }).not.toThrow()
  120. const result = mockGetDependentVars(varInputs)
  121. expect(result[0]).toEqual(['{workflow', 'node', 'output}'])
  122. })
  123. })
  124. /**
  125. * Integration test to simulate the complete workflow scenario
  126. */
  127. describe('Plugin Tool Workflow Integration', () => {
  128. /**
  129. * Simulate the scenario where plugin metadata is incomplete or corrupted
  130. * This can happen when:
  131. * 1. Plugin is being loaded from marketplace but metadata request fails
  132. * 2. Plugin configuration is corrupted in database
  133. * 3. Network issues during plugin loading
  134. */
  135. it('should reproduce the client-side exception scenario', () => {
  136. // Mock incomplete plugin data that could cause the error
  137. const incompletePluginData = {
  138. // Missing or null uniqueIdentifier
  139. uniqueIdentifier: null,
  140. meta: null,
  141. minimum_dify_version: undefined,
  142. }
  143. // This simulates the error path that leads to the white screen
  144. expect(() => {
  145. // Simulate the code path in switch-plugin-version.tsx:29
  146. // The actual problematic code doesn't use optional chaining
  147. const _pluginId = (incompletePluginData.uniqueIdentifier as any).split(':')[0]
  148. }).toThrow('Cannot read properties of null (reading \'split\')')
  149. })
  150. /**
  151. * Test the scenario mentioned in the issue where plugin tools are loaded in workflow
  152. */
  153. it('should simulate plugin tool loading in workflow context', () => {
  154. // Mock the workflow context where plugin tools are being loaded
  155. const workflowPluginTools = [
  156. {
  157. provider_name: 'test-plugin',
  158. uniqueIdentifier: null, // This is the problematic case
  159. tool_name: 'test-tool',
  160. },
  161. {
  162. provider_name: 'valid-plugin',
  163. uniqueIdentifier: 'valid-plugin:1.0.0',
  164. tool_name: 'valid-tool',
  165. },
  166. ]
  167. // Process each plugin tool
  168. workflowPluginTools.forEach((tool, _index) => {
  169. if (tool.uniqueIdentifier === null) {
  170. // This reproduces the exact error scenario
  171. expect(() => {
  172. const _pluginId = (tool.uniqueIdentifier as any).split(':')[0]
  173. }).toThrow()
  174. }
  175. else {
  176. // Valid tools should work fine
  177. expect(() => {
  178. const _pluginId = tool.uniqueIdentifier.split(':')[0]
  179. }).not.toThrow()
  180. }
  181. })
  182. })
  183. })