1use devboy_core::{
2 Error, KnowledgeBaseProvider, MeetingNotesProvider, MessengerProvider, Provider, Result,
3 ToolEnricher,
4};
5
6use crate::context::{
7 ClickUpScope, ConfluenceAuthConfig, ConfluenceScope, GitHubScope, GitLabScope, JiraScope,
8 ProviderConfig, ProviderMetadata, ProxyConfig, SlackScope,
9};
10
11pub fn create_provider(
21 config: &ProviderConfig,
22 proxy: Option<&ProxyConfig>,
23) -> Result<Box<dyn Provider>> {
24 match config {
25 ProviderConfig::GitLab {
26 base_url,
27 access_token,
28 scope,
29 ..
30 } => match scope {
31 GitLabScope::Project { id } => {
32 let client = if let Some(proxy) = proxy {
33 devboy_gitlab::GitLabClient::with_base_url(
34 &proxy.url,
35 id,
36 access_token.clone(),
37 )
38 .with_proxy(proxy.headers.clone())
39 } else {
40 devboy_gitlab::GitLabClient::with_base_url(
41 base_url,
42 id,
43 access_token.clone(),
44 )
45 };
46 Ok(Box::new(client))
47 }
48 GitLabScope::Group { id } => Err(Error::ProviderUnsupported {
49 provider: "gitlab".into(),
50 operation: format!("group scope (group_id: {id}) not yet implemented"),
51 }),
52 GitLabScope::Global => Err(Error::ProviderUnsupported {
53 provider: "gitlab".into(),
54 operation: "global scope not yet implemented".into(),
55 }),
56 },
57
58 ProviderConfig::GitHub {
59 base_url,
60 access_token,
61 scope,
62 ..
63 } => match scope {
64 GitHubScope::Repository { owner, repo } => {
65 Ok(Box::new(devboy_github::GitHubClient::with_base_url(
66 base_url,
67 owner,
68 repo,
69 access_token.clone(),
70 )))
71 }
72 GitHubScope::Organization { name } => Err(Error::ProviderUnsupported {
73 provider: "github".into(),
74 operation: format!("organization scope (org: {name}) not yet implemented"),
75 }),
76 GitHubScope::Global => Err(Error::ProviderUnsupported {
77 provider: "github".into(),
78 operation: "global scope not yet implemented".into(),
79 }),
80 },
81
82 ProviderConfig::ClickUp {
83 access_token,
84 scope,
85 ..
86 } => match scope {
87 ClickUpScope::List { id, team_id } => {
88 let mut client = devboy_clickup::ClickUpClient::new(id, access_token.clone());
89 if let Some(tid) = team_id {
90 client = client.with_team_id(tid);
91 }
92 Ok(Box::new(client))
93 }
94 },
95
96 ProviderConfig::Jira {
97 base_url,
98 access_token,
99 email,
100 scope,
101 flavor,
102 ..
103 } => match scope {
104 JiraScope::Project { key } => {
105 let mut client = if let Some(proxy) = proxy {
106 devboy_jira::JiraClient::new(
107 &proxy.url,
108 key,
109 email,
110 access_token.clone(),
111 )
112 .with_proxy(proxy.headers.clone())
113 .with_instance_url(base_url)
114 } else {
115 devboy_jira::JiraClient::new(base_url, key, email, access_token.clone())
116 };
117 if let Some(f) = flavor {
118 client = client.with_flavor(*f);
119 }
120 Ok(Box::new(client))
121 }
122 JiraScope::MultiProject { keys } => Err(Error::ProviderUnsupported {
123 provider: "jira".into(),
124 operation: format!(
125 "multi-project scope ({}) not yet implemented",
126 keys.join(", ")
127 ),
128 }),
129 },
130
131 ProviderConfig::Confluence { .. } => Err(Error::ProviderUnsupported {
132 provider: "confluence".into(),
133 operation: "Confluence is a KnowledgeBaseProvider, not a Provider. Use create_knowledge_base_provider() instead.".into(),
134 }),
135
136 ProviderConfig::Fireflies { .. } => Err(Error::ProviderUnsupported {
137 provider: "fireflies".into(),
138 operation: "Fireflies is a MeetingNotesProvider, not a Provider. Use create_meeting_notes_provider() instead.".into(),
139 }),
140
141 ProviderConfig::Slack { .. } => Err(Error::ProviderUnsupported {
142 provider: "slack".into(),
143 operation: "Slack is a MessengerProvider, not a Provider. Use create_messenger_provider() instead.".into(),
144 }),
145
146 ProviderConfig::Custom { name, .. } => Err(Error::ProviderNotFound(format!(
147 "custom provider '{name}' not yet supported"
148 ))),
149 }
150}
151
152pub fn create_knowledge_base_provider(
153 config: &ProviderConfig,
154 proxy: Option<&ProxyConfig>,
155) -> Result<Box<dyn KnowledgeBaseProvider>> {
156 match config {
157 ProviderConfig::Confluence {
158 base_url,
159 auth,
160 api_version,
161 scope: ConfluenceScope::Space { .. },
162 ..
163 } => {
164 let client = if let Some(proxy) = proxy {
165 devboy_confluence::ConfluenceClient::new(
166 &proxy.url,
167 devboy_confluence::ConfluenceAuth::None,
168 )
169 .with_api_version(api_version.as_deref())
170 .with_proxy(proxy.headers.clone())
171 .with_instance_url(base_url)
174 } else {
175 devboy_confluence::ConfluenceClient::new(base_url, confluence_auth(auth))
176 .with_api_version(api_version.as_deref())
177 };
178 Ok(Box::new(client))
179 }
180 other => Err(Error::ProviderUnsupported {
181 provider: other.provider_name().into(),
182 operation: "not a knowledge base provider".into(),
183 }),
184 }
185}
186
187pub fn create_knowledge_base_enricher(config: &ProviderConfig) -> Option<Box<dyn ToolEnricher>> {
193 match config {
194 ProviderConfig::Confluence { .. } => {
195 Some(Box::new(devboy_confluence::ConfluenceSchemaEnricher::new()))
196 }
197 _ => None,
198 }
199}
200
201pub fn create_meeting_notes_provider(
206 config: &ProviderConfig,
207) -> Result<Box<dyn MeetingNotesProvider>> {
208 match config {
209 ProviderConfig::Fireflies { api_key, .. } => Ok(Box::new(
210 devboy_fireflies::FirefliesClient::new(api_key.clone()),
211 )),
212 other => Err(Error::ProviderUnsupported {
213 provider: other.provider_name().into(),
214 operation: "not a meeting notes provider".into(),
215 }),
216 }
217}
218
219pub fn create_messenger_provider(config: &ProviderConfig) -> Result<Box<dyn MessengerProvider>> {
220 match config {
221 ProviderConfig::Slack {
222 base_url,
223 access_token,
224 scope: SlackScope::Workspace { .. },
225 required_scopes,
226 ..
227 } => Ok(Box::new(
228 devboy_slack::SlackClient::new(access_token.clone())
229 .with_base_url(base_url)
230 .with_required_scopes(required_scopes.clone()),
231 )),
232 other => Err(Error::ProviderUnsupported {
233 provider: other.provider_name().into(),
234 operation: "not a messenger provider".into(),
235 }),
236 }
237}
238
239pub fn create_enricher(
246 config: &ProviderConfig,
247 metadata: Option<&ProviderMetadata>,
248) -> Option<Box<dyn ToolEnricher>> {
249 match config {
250 ProviderConfig::GitLab { .. } => Some(Box::new(devboy_gitlab::GitLabSchemaEnricher)),
251 ProviderConfig::GitHub { .. } => Some(Box::new(devboy_github::GitHubSchemaEnricher)),
252 ProviderConfig::ClickUp { .. } => {
253 let meta = metadata?;
254 let clickup_meta: devboy_clickup::ClickUpMetadata =
255 serde_json::from_value(meta.data.clone()).ok()?;
256 Some(Box::new(devboy_clickup::ClickUpSchemaEnricher::new(
257 clickup_meta,
258 )))
259 }
260 ProviderConfig::Jira { .. } => {
261 let meta = metadata?;
262 let jira_meta: devboy_jira::JiraMetadata =
263 serde_json::from_value(meta.data.clone()).ok()?;
264 Some(Box::new(devboy_jira::JiraSchemaEnricher::new(jira_meta)))
265 }
266 ProviderConfig::Confluence { .. } => None,
267 ProviderConfig::Fireflies { .. } => {
268 Some(Box::new(devboy_fireflies::FirefliesSchemaEnricher))
269 }
270 ProviderConfig::Slack { .. } => None,
271 ProviderConfig::Custom { .. } => None,
272 }
273}
274
275fn confluence_auth(auth: &ConfluenceAuthConfig) -> devboy_confluence::ConfluenceAuth {
276 match auth {
277 ConfluenceAuthConfig::BearerToken { token } => {
278 devboy_confluence::ConfluenceAuth::BearerToken(token.clone())
279 }
280 ConfluenceAuthConfig::Basic { username, password } => {
281 devboy_confluence::ConfluenceAuth::Basic {
282 username: username.clone(),
283 password: password.clone(),
284 }
285 }
286 }
287}
288
289#[cfg(test)]
290mod tests {
291 use super::*;
292 use crate::context::*;
293 use devboy_core::{IssueProvider, KnowledgeBaseProvider};
294 use httpmock::Method::GET;
295 use httpmock::MockServer;
296 use std::collections::HashMap;
297
298 #[test]
299 fn test_create_gitlab_project_provider() {
300 let config = ProviderConfig::GitLab {
301 base_url: "https://gitlab.com".into(),
302 access_token: "test-token".into(),
303 scope: GitLabScope::Project { id: "12345".into() },
304 extra: HashMap::new(),
305 };
306 let provider = create_provider(&config, None);
307 assert!(provider.is_ok());
308 assert_eq!(
309 IssueProvider::provider_name(provider.unwrap().as_ref()),
310 "gitlab"
311 );
312 }
313
314 #[test]
315 fn test_create_github_repo_provider() {
316 let config = ProviderConfig::GitHub {
317 base_url: "https://api.github.com".into(),
318 access_token: "ghp_test".into(),
319 scope: GitHubScope::Repository {
320 owner: "meteora-pro".into(),
321 repo: "devboy-tools".into(),
322 },
323 extra: HashMap::new(),
324 };
325 let provider = create_provider(&config, None);
326 assert!(provider.is_ok());
327 assert_eq!(
328 IssueProvider::provider_name(provider.unwrap().as_ref()),
329 "github"
330 );
331 }
332
333 #[test]
334 fn test_create_clickup_provider() {
335 let config = ProviderConfig::ClickUp {
336 access_token: "pk_test".into(),
337 scope: ClickUpScope::List {
338 id: "list123".into(),
339 team_id: Some("team456".into()),
340 },
341 extra: HashMap::new(),
342 };
343 let provider = create_provider(&config, None);
344 assert!(provider.is_ok());
345 assert_eq!(
346 IssueProvider::provider_name(provider.unwrap().as_ref()),
347 "clickup"
348 );
349 }
350
351 #[test]
352 fn test_create_jira_provider() {
353 let config = ProviderConfig::Jira {
354 base_url: "https://myorg.atlassian.net".into(),
355 access_token: "jira-token".into(),
356 email: "user@example.com".into(),
357 scope: JiraScope::Project { key: "PROJ".into() },
358 flavor: None,
359 extra: HashMap::new(),
360 };
361 let provider = create_provider(&config, None);
362 assert!(provider.is_ok());
363 assert_eq!(
364 IssueProvider::provider_name(provider.unwrap().as_ref()),
365 "jira"
366 );
367 }
368
369 #[test]
370 fn test_create_confluence_knowledge_base_provider() {
371 let config = ProviderConfig::Confluence {
372 base_url: "https://wiki.example.com".into(),
373 auth: ConfluenceAuthConfig::BearerToken {
374 token: "test-token".into(),
375 },
376 scope: ConfluenceScope::Space {
377 key: Some("ENG".into()),
378 },
379 api_version: Some("v1".into()),
380 extra: HashMap::new(),
381 };
382 let provider = create_knowledge_base_provider(&config, None);
383 assert!(provider.is_ok());
384 assert_eq!(
385 KnowledgeBaseProvider::provider_name(provider.unwrap().as_ref()),
386 "confluence"
387 );
388 }
389
390 #[test]
391 fn test_create_confluence_knowledge_base_enricher() {
392 let config = ProviderConfig::Confluence {
393 base_url: "https://wiki.example.com".into(),
394 auth: ConfluenceAuthConfig::BearerToken {
395 token: "test-token".into(),
396 },
397 scope: ConfluenceScope::Space {
398 key: Some("ENG".into()),
399 },
400 api_version: Some("v1".into()),
401 extra: HashMap::new(),
402 };
403 let enricher = create_knowledge_base_enricher(&config);
404 assert!(enricher.is_some());
405 assert_eq!(
406 enricher.unwrap().supported_categories(),
407 &[devboy_core::ToolCategory::KnowledgeBase]
408 );
409 }
410
411 #[test]
412 fn test_confluence_is_not_regular_provider() {
413 let config = ProviderConfig::Confluence {
414 base_url: "https://wiki.example.com".into(),
415 auth: ConfluenceAuthConfig::BearerToken {
416 token: "test-token".into(),
417 },
418 scope: ConfluenceScope::Space { key: None },
419 api_version: None,
420 extra: HashMap::new(),
421 };
422
423 let result = create_provider(&config, None);
424 assert!(matches!(
425 result,
426 Err(Error::ProviderUnsupported { provider, .. }) if provider == "confluence"
427 ));
428 }
429
430 #[tokio::test]
431 async fn test_create_confluence_knowledge_base_provider_honors_api_version() {
432 let server = MockServer::start();
433 let mock = server.mock(|when, then| {
434 when.method(GET)
435 .path("/api/v2/space")
436 .query_param("limit", "100")
437 .query_param("type", "global,personal");
438 then.status(200)
439 .header("content-type", "application/json")
440 .body(r#"{"results":[],"start":0,"limit":100,"size":0,"_links":{}}"#);
441 });
442
443 let config = ProviderConfig::Confluence {
444 base_url: server.base_url(),
445 auth: ConfluenceAuthConfig::BearerToken {
446 token: "test-token".into(),
447 },
448 scope: ConfluenceScope::Space { key: None },
449 api_version: Some("v2".into()),
450 extra: HashMap::new(),
451 };
452
453 let provider = create_knowledge_base_provider(&config, None).unwrap();
454 let _ = provider.get_spaces().await.unwrap();
455
456 mock.assert();
457 }
458
459 #[test]
460 fn test_create_custom_provider_unsupported() {
461 let config = ProviderConfig::Custom {
462 name: "my-plugin".into(),
463 config: HashMap::new(),
464 };
465 let result = create_provider(&config, None);
466 assert!(result.is_err());
467 }
468
469 #[test]
470 fn test_gitlab_group_scope_unsupported() {
471 let config = ProviderConfig::GitLab {
472 base_url: "https://gitlab.com".into(),
473 access_token: "token".into(),
474 scope: GitLabScope::Group {
475 id: "group1".into(),
476 },
477 extra: HashMap::new(),
478 };
479 let result = create_provider(&config, None);
480 assert!(result.is_err());
481 }
482
483 #[test]
484 fn test_create_enricher_gitlab_static() {
485 let config = ProviderConfig::GitLab {
486 base_url: "https://gitlab.com".into(),
487 access_token: "token".into(),
488 scope: GitLabScope::Project { id: "123".into() },
489 extra: HashMap::new(),
490 };
491 let enricher = create_enricher(&config, None);
492 assert!(enricher.is_some());
493 }
494
495 #[test]
496 fn test_create_enricher_github_static() {
497 let config = ProviderConfig::GitHub {
498 base_url: "https://api.github.com".into(),
499 access_token: "token".into(),
500 scope: GitHubScope::Repository {
501 owner: "test".into(),
502 repo: "test".into(),
503 },
504 extra: HashMap::new(),
505 };
506 let enricher = create_enricher(&config, None);
507 assert!(enricher.is_some());
508 }
509
510 #[test]
511 fn test_create_enricher_clickup_needs_metadata() {
512 let config = ProviderConfig::ClickUp {
513 access_token: "token".into(),
514 scope: ClickUpScope::List {
515 id: "list1".into(),
516 team_id: None,
517 },
518 extra: HashMap::new(),
519 };
520 assert!(create_enricher(&config, None).is_none());
522
523 let meta = ProviderMetadata::new(serde_json::json!({
525 "statuses": [{ "name": "To Do" }],
526 "custom_fields": []
527 }));
528 assert!(create_enricher(&config, Some(&meta)).is_some());
529 }
530
531 #[test]
532 fn test_create_enricher_jira_needs_metadata() {
533 let config = ProviderConfig::Jira {
534 base_url: "https://test.atlassian.net".into(),
535 access_token: "token".into(),
536 email: "test@test.com".into(),
537 scope: JiraScope::Project { key: "PROJ".into() },
538 flavor: None,
539 extra: HashMap::new(),
540 };
541 assert!(create_enricher(&config, None).is_none());
543
544 let meta = ProviderMetadata::new(serde_json::json!({
546 "flavor": "cloud",
547 "projects": {
548 "PROJ": {
549 "issue_types": [],
550 "priorities": [],
551 "components": [],
552 "link_types": [],
553 "custom_fields": []
554 }
555 }
556 }));
557 assert!(create_enricher(&config, Some(&meta)).is_some());
558 }
559
560 #[test]
563 fn test_create_gitlab_provider_with_proxy() {
564 let config = ProviderConfig::GitLab {
565 base_url: "https://gitlab.internal.com".into(),
566 access_token: "test-token".into(),
567 scope: GitLabScope::Project { id: "99".into() },
568 extra: HashMap::new(),
569 };
570 let mut headers = HashMap::new();
571 headers.insert("X-Proxy-Auth".into(), "proxy-secret".into());
572 let proxy = ProxyConfig {
573 url: "https://proxy.example.com/gitlab".into(),
574 headers,
575 };
576 let provider = create_provider(&config, Some(&proxy));
577 assert!(provider.is_ok());
578 assert_eq!(
579 IssueProvider::provider_name(provider.unwrap().as_ref()),
580 "gitlab"
581 );
582 }
583
584 #[test]
585 fn test_create_jira_provider_with_proxy() {
586 let config = ProviderConfig::Jira {
587 base_url: "https://jira.mycompany.com".into(),
588 access_token: "jira-token".into(),
589 email: "dev@mycompany.com".into(),
590 scope: JiraScope::Project { key: "DEV".into() },
591 flavor: None,
592 extra: HashMap::new(),
593 };
594 let mut headers = HashMap::new();
595 headers.insert("X-Proxy-Auth".into(), "secret".into());
596 headers.insert("X-Route".into(), "jira-dc".into());
597 let proxy = ProxyConfig {
598 url: "https://proxy.internal/jira".into(),
599 headers,
600 };
601 let provider = create_provider(&config, Some(&proxy));
602 assert!(provider.is_ok());
603 assert_eq!(
604 IssueProvider::provider_name(provider.unwrap().as_ref()),
605 "jira"
606 );
607 }
608
609 #[test]
610 fn test_create_jira_provider_with_flavor_cloud() {
611 let config = ProviderConfig::Jira {
612 base_url: "https://myorg.atlassian.net".into(),
613 access_token: "tok".into(),
614 email: "a@b.com".into(),
615 scope: JiraScope::Project { key: "CLD".into() },
616 flavor: Some(devboy_jira::JiraFlavor::Cloud),
617 extra: HashMap::new(),
618 };
619 let provider = create_provider(&config, None);
620 assert!(provider.is_ok());
621 }
622
623 #[test]
624 fn test_create_jira_provider_with_flavor_self_hosted() {
625 let config = ProviderConfig::Jira {
626 base_url: "https://jira.local".into(),
627 access_token: "tok".into(),
628 email: "a@b.com".into(),
629 scope: JiraScope::Project { key: "SH".into() },
630 flavor: Some(devboy_jira::JiraFlavor::SelfHosted),
631 extra: HashMap::new(),
632 };
633 let provider = create_provider(&config, None);
634 assert!(provider.is_ok());
635 }
636
637 #[test]
638 fn test_create_jira_provider_with_proxy_and_flavor_override() {
639 let config = ProviderConfig::Jira {
640 base_url: "https://jira.dc.mycompany.com".into(),
641 access_token: "tok".into(),
642 email: "a@b.com".into(),
643 scope: JiraScope::Project { key: "DC".into() },
644 flavor: Some(devboy_jira::JiraFlavor::SelfHosted),
645 extra: HashMap::new(),
646 };
647 let proxy = ProxyConfig {
648 url: "https://proxy.internal/jira".into(),
649 headers: HashMap::new(),
650 };
651 let provider = create_provider(&config, Some(&proxy));
652 assert!(provider.is_ok());
653 }
654
655 #[test]
658 fn test_gitlab_global_scope_unsupported() {
659 let config = ProviderConfig::GitLab {
660 base_url: "https://gitlab.com".into(),
661 access_token: "tok".into(),
662 scope: GitLabScope::Global,
663 extra: HashMap::new(),
664 };
665 let result = create_provider(&config, None);
666 match result {
667 Err(e) => assert!(e.to_string().contains("global scope")),
668 Ok(_) => panic!("expected error for global scope"),
669 }
670 }
671
672 #[test]
673 fn test_github_organization_scope_unsupported() {
674 let config = ProviderConfig::GitHub {
675 base_url: "https://api.github.com".into(),
676 access_token: "tok".into(),
677 scope: GitHubScope::Organization {
678 name: "myorg".into(),
679 },
680 extra: HashMap::new(),
681 };
682 let result = create_provider(&config, None);
683 match result {
684 Err(e) => assert!(e.to_string().contains("organization scope")),
685 Ok(_) => panic!("expected error for organization scope"),
686 }
687 }
688
689 #[test]
690 fn test_github_global_scope_unsupported() {
691 let config = ProviderConfig::GitHub {
692 base_url: "https://api.github.com".into(),
693 access_token: "tok".into(),
694 scope: GitHubScope::Global,
695 extra: HashMap::new(),
696 };
697 let result = create_provider(&config, None);
698 assert!(result.is_err());
699 }
700
701 #[test]
702 fn test_jira_multi_project_scope_unsupported() {
703 let config = ProviderConfig::Jira {
704 base_url: "https://test.atlassian.net".into(),
705 access_token: "tok".into(),
706 email: "a@b.com".into(),
707 scope: JiraScope::MultiProject {
708 keys: vec!["A".into(), "B".into()],
709 },
710 flavor: None,
711 extra: HashMap::new(),
712 };
713 let result = create_provider(&config, None);
714 match result {
715 Err(e) => assert!(e.to_string().contains("multi-project")),
716 Ok(_) => panic!("expected error for multi-project scope"),
717 }
718 }
719
720 #[test]
723 fn test_create_clickup_provider_without_team_id() {
724 let config = ProviderConfig::ClickUp {
725 access_token: "pk_test".into(),
726 scope: ClickUpScope::List {
727 id: "list999".into(),
728 team_id: None,
729 },
730 extra: HashMap::new(),
731 };
732 let provider = create_provider(&config, None);
733 assert!(provider.is_ok());
734 assert_eq!(
735 IssueProvider::provider_name(provider.unwrap().as_ref()),
736 "clickup"
737 );
738 }
739
740 #[test]
743 fn test_create_enricher_custom_returns_none() {
744 let config = ProviderConfig::Custom {
745 name: "custom-plugin".into(),
746 config: HashMap::new(),
747 };
748 assert!(create_enricher(&config, None).is_none());
749 }
750
751 #[test]
752 fn test_create_knowledge_base_enricher_non_kb_returns_none() {
753 let config = ProviderConfig::GitHub {
754 base_url: "https://api.github.com".into(),
755 access_token: "tok".into(),
756 scope: GitHubScope::Repository {
757 owner: "test".into(),
758 repo: "test".into(),
759 },
760 extra: HashMap::new(),
761 };
762 assert!(create_knowledge_base_enricher(&config).is_none());
763 }
764
765 #[test]
768 fn test_create_enricher_clickup_invalid_metadata_returns_none() {
769 let config = ProviderConfig::ClickUp {
770 access_token: "token".into(),
771 scope: ClickUpScope::List {
772 id: "list1".into(),
773 team_id: None,
774 },
775 extra: HashMap::new(),
776 };
777 let meta = ProviderMetadata::new(serde_json::json!("invalid_data"));
778 assert!(create_enricher(&config, Some(&meta)).is_none());
779 }
780
781 #[test]
782 fn test_create_enricher_jira_invalid_metadata_returns_none() {
783 let config = ProviderConfig::Jira {
784 base_url: "https://test.atlassian.net".into(),
785 access_token: "token".into(),
786 email: "a@b.com".into(),
787 scope: JiraScope::Project { key: "X".into() },
788 flavor: None,
789 extra: HashMap::new(),
790 };
791 let meta = ProviderMetadata::new(serde_json::json!("not_valid"));
792 assert!(create_enricher(&config, Some(&meta)).is_none());
793 }
794}