qualyx 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (100) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +523 -0
  3. package/dist/cli/commands/init.d.ts +6 -0
  4. package/dist/cli/commands/init.d.ts.map +1 -0
  5. package/dist/cli/commands/init.js +124 -0
  6. package/dist/cli/commands/init.js.map +1 -0
  7. package/dist/cli/commands/list.d.ts +3 -0
  8. package/dist/cli/commands/list.d.ts.map +1 -0
  9. package/dist/cli/commands/list.js +122 -0
  10. package/dist/cli/commands/list.js.map +1 -0
  11. package/dist/cli/commands/run.d.ts +12 -0
  12. package/dist/cli/commands/run.d.ts.map +1 -0
  13. package/dist/cli/commands/run.js +160 -0
  14. package/dist/cli/commands/run.js.map +1 -0
  15. package/dist/cli/commands/schedule.d.ts +19 -0
  16. package/dist/cli/commands/schedule.d.ts.map +1 -0
  17. package/dist/cli/commands/schedule.js +240 -0
  18. package/dist/cli/commands/schedule.js.map +1 -0
  19. package/dist/cli/commands/validate.d.ts +3 -0
  20. package/dist/cli/commands/validate.d.ts.map +1 -0
  21. package/dist/cli/commands/validate.js +47 -0
  22. package/dist/cli/commands/validate.js.map +1 -0
  23. package/dist/cli/index.d.ts +3 -0
  24. package/dist/cli/index.d.ts.map +1 -0
  25. package/dist/cli/index.js +194 -0
  26. package/dist/cli/index.js.map +1 -0
  27. package/dist/core/claude-runner.d.ts +23 -0
  28. package/dist/core/claude-runner.d.ts.map +1 -0
  29. package/dist/core/claude-runner.js +196 -0
  30. package/dist/core/claude-runner.js.map +1 -0
  31. package/dist/core/config-loader.d.ts +137 -0
  32. package/dist/core/config-loader.d.ts.map +1 -0
  33. package/dist/core/config-loader.js +239 -0
  34. package/dist/core/config-loader.js.map +1 -0
  35. package/dist/core/executor.d.ts +75 -0
  36. package/dist/core/executor.d.ts.map +1 -0
  37. package/dist/core/executor.js +337 -0
  38. package/dist/core/executor.js.map +1 -0
  39. package/dist/core/index.d.ts +6 -0
  40. package/dist/core/index.d.ts.map +1 -0
  41. package/dist/core/index.js +7 -0
  42. package/dist/core/index.js.map +1 -0
  43. package/dist/core/prompt-builder.d.ts +24 -0
  44. package/dist/core/prompt-builder.d.ts.map +1 -0
  45. package/dist/core/prompt-builder.js +145 -0
  46. package/dist/core/prompt-builder.js.map +1 -0
  47. package/dist/core/retry-handler.d.ts +42 -0
  48. package/dist/core/retry-handler.d.ts.map +1 -0
  49. package/dist/core/retry-handler.js +126 -0
  50. package/dist/core/retry-handler.js.map +1 -0
  51. package/dist/index.d.ts +3 -0
  52. package/dist/index.d.ts.map +1 -0
  53. package/dist/index.js +16 -0
  54. package/dist/index.js.map +1 -0
  55. package/dist/integrations/email.d.ts +38 -0
  56. package/dist/integrations/email.d.ts.map +1 -0
  57. package/dist/integrations/email.js +216 -0
  58. package/dist/integrations/email.js.map +1 -0
  59. package/dist/integrations/index.d.ts +5 -0
  60. package/dist/integrations/index.d.ts.map +1 -0
  61. package/dist/integrations/index.js +5 -0
  62. package/dist/integrations/index.js.map +1 -0
  63. package/dist/integrations/jira.d.ts +68 -0
  64. package/dist/integrations/jira.d.ts.map +1 -0
  65. package/dist/integrations/jira.js +288 -0
  66. package/dist/integrations/jira.js.map +1 -0
  67. package/dist/integrations/slack.d.ts +66 -0
  68. package/dist/integrations/slack.d.ts.map +1 -0
  69. package/dist/integrations/slack.js +192 -0
  70. package/dist/integrations/slack.js.map +1 -0
  71. package/dist/integrations/teams.d.ts +72 -0
  72. package/dist/integrations/teams.d.ts.map +1 -0
  73. package/dist/integrations/teams.js +197 -0
  74. package/dist/integrations/teams.js.map +1 -0
  75. package/dist/reporters/console.d.ts +83 -0
  76. package/dist/reporters/console.d.ts.map +1 -0
  77. package/dist/reporters/console.js +299 -0
  78. package/dist/reporters/console.js.map +1 -0
  79. package/dist/reporters/html.d.ts +29 -0
  80. package/dist/reporters/html.d.ts.map +1 -0
  81. package/dist/reporters/html.js +105 -0
  82. package/dist/reporters/html.js.map +1 -0
  83. package/dist/storage/results.d.ts +61 -0
  84. package/dist/storage/results.d.ts.map +1 -0
  85. package/dist/storage/results.js +111 -0
  86. package/dist/storage/results.js.map +1 -0
  87. package/dist/storage/sqlite.d.ts +70 -0
  88. package/dist/storage/sqlite.d.ts.map +1 -0
  89. package/dist/storage/sqlite.js +240 -0
  90. package/dist/storage/sqlite.js.map +1 -0
  91. package/dist/types/index.d.ts +1239 -0
  92. package/dist/types/index.d.ts.map +1 -0
  93. package/dist/types/index.js +105 -0
  94. package/dist/types/index.js.map +1 -0
  95. package/package.json +75 -0
  96. package/templates/crontab.hbs +24 -0
  97. package/templates/github-schedule.yml.hbs +153 -0
  98. package/templates/prompt.md.hbs +147 -0
  99. package/templates/report.html.hbs +423 -0
  100. package/templates/slack-message.json.hbs +93 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAMxB,eAAO,MAAM,UAAU;;;;;;;;;;;;IAOrB,CAAC;AAEH,eAAO,MAAM,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAWrB,CAAC;AAEH,eAAO,MAAM,UAAU;;;;;;;;;;;;EAIrB,CAAC;AAEH,eAAO,MAAM,uBAAuB;;;;;;;;;;;;EAIlC,CAAC;AAEH,eAAO,MAAM,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAQpB,CAAC;AAEH,eAAO,MAAM,0BAA0B;;;;;;;;;;;;EAIrC,CAAC;AAEH,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAG7B,CAAC;AAMH,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;EAM5B,CAAC;AAEH,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAW5B,CAAC;AAEH,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;EAK5B,CAAC;AAEH,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;EAS3B,CAAC;AAEH,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAI9B,CAAC;AAEH,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAE7B,CAAC;AAEH,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAK7B,CAAC;AAMH,MAAM,MAAM,IAAI,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,UAAU,CAAC,CAAC;AAC9C,MAAM,MAAM,IAAI,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,UAAU,CAAC,CAAC;AAC9C,MAAM,MAAM,IAAI,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,UAAU,CAAC,CAAC;AAC9C,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAC;AACxE,MAAM,MAAM,GAAG,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,SAAS,CAAC,CAAC;AAC5C,MAAM,MAAM,oBAAoB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,0BAA0B,CAAC,CAAC;AAC9E,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAC9D,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAC5D,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAC5D,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAC5D,MAAM,MAAM,UAAU,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAC1D,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAChE,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAC9D,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAM9D,MAAM,MAAM,UAAU,GAAG,QAAQ,GAAG,QAAQ,GAAG,SAAS,GAAG,SAAS,CAAC;AAErE,MAAM,WAAW,kBAAkB;IACjC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,UAAU,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,kBAAkB,CAAC;CAC9B;AAED,MAAM,WAAW,gBAAgB;IAC/B,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,OAAO,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,UAAU,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,UAAU,EAAE,CAAC;IACpB,WAAW,EAAE,gBAAgB,EAAE,CAAC;IAChC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,kBAAkB,CAAC;CAC9B;AAED,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,UAAU,EAAE,CAAC;IACtB,WAAW,EAAE,MAAM,CAAC;CACrB;AAMD,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,OAAO,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,UAAU,CAAC;IACnB,KAAK,EAAE,UAAU,EAAE,CAAC;IACpB,WAAW,EAAE,gBAAgB,EAAE,CAAC;IAChC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAMD,MAAM,WAAW,aAAa;IAC5B,GAAG,EAAE,GAAG,CAAC;IACT,IAAI,EAAE,IAAI,CAAC;IACX,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACpC,eAAe,CAAC,EAAE;QAChB,KAAK,EAAE,MAAM,CAAC;QACd,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,UAAU,CAAC,EAAE,MAAM,CAAC;KACrB,CAAC;IACF,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAMD,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,OAAO,CAAC;CAClB;AAMD,MAAM,WAAW,SAAS;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,UAAU,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,gBAAgB,EAAE,MAAM,CAAC;CAC1B;AAMD,MAAM,WAAW,UAAU;IACzB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED,MAAM,WAAW,WAAW;IAC1B,MAAM,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,eAAe;IAC9B,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAMD,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,MAAM,GAAG,QAAQ,CAAC;IAC1B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAMD,MAAM,WAAW,wBAAwB;IACvC,SAAS,EAAE,SAAS,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,YAAY,CAAC;CACtB;AAED,MAAM,WAAW,gBAAgB;IAC/B,UAAU,EAAE,UAAU,CAAC;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,YAAY,CAAC;CACtB"}
@@ -0,0 +1,105 @@
1
+ import { z } from 'zod';
2
+ // ============================================================
3
+ // Zod Schemas for Configuration Validation
4
+ // ============================================================
5
+ export const StepSchema = z.union([
6
+ z.string(),
7
+ z.object({
8
+ action: z.string(),
9
+ hint: z.string().optional(),
10
+ caution: z.string().optional(),
11
+ }),
12
+ ]);
13
+ export const RuleSchema = z.object({
14
+ id: z.string().min(1),
15
+ name: z.string().min(1),
16
+ severity: z.enum(['critical', 'high', 'medium', 'low']).default('medium'),
17
+ timeout: z.number().positive().optional(),
18
+ steps: z.array(StepSchema).min(1),
19
+ validations: z.array(z.string()).optional(),
20
+ on_failure: z.array(z.string()).optional(),
21
+ test_data: z.record(z.unknown()).optional(),
22
+ schedule: z.string().optional(), // Cron expression for scheduling
23
+ skip_setup: z.boolean().optional(), // Skip setup block for this rule
24
+ });
25
+ export const AuthSchema = z.object({
26
+ type: z.enum(['form-login', 'basic', 'bearer', 'cookie', 'none']).default('none'),
27
+ credentials: z.record(z.string()).optional(),
28
+ login_url: z.string().url().optional(),
29
+ });
30
+ export const ScreenshotsConfigSchema = z.object({
31
+ on_failure: z.boolean().default(true),
32
+ on_success: z.boolean().default(false),
33
+ each_step: z.boolean().default(false),
34
+ });
35
+ export const AppSchema = z.object({
36
+ name: z.string().min(1),
37
+ url: z.string().url(),
38
+ environments: z.record(z.string().url()).optional(),
39
+ auth: AuthSchema.optional(),
40
+ screenshots: ScreenshotsConfigSchema.optional(),
41
+ setup: z.array(z.string()).optional(), // Setup steps to run before rules
42
+ rules: z.array(RuleSchema).min(1),
43
+ });
44
+ export const OrganizationDefaultsSchema = z.object({
45
+ timeout: z.number().positive().default(30000),
46
+ retries: z.number().min(0).max(5).default(2),
47
+ headless: z.boolean().default(true),
48
+ });
49
+ export const OrganizationSchema = z.object({
50
+ name: z.string().min(1),
51
+ defaults: OrganizationDefaultsSchema.optional(),
52
+ });
53
+ // ============================================================
54
+ // Notification & Integration Schemas
55
+ // ============================================================
56
+ export const SlackConfigSchema = z.object({
57
+ webhook_url: z.string().min(1),
58
+ on_failure: z.boolean().default(true),
59
+ on_success: z.boolean().default(false),
60
+ channel: z.string().optional(), // Override channel (if webhook supports it)
61
+ mention_on_failure: z.array(z.string()).optional(), // User IDs to mention on failure
62
+ });
63
+ export const EmailConfigSchema = z.object({
64
+ smtp_host: z.string().min(1),
65
+ smtp_port: z.number().default(587),
66
+ smtp_secure: z.boolean().default(false), // true for 465, false for other ports
67
+ smtp_user: z.string().min(1),
68
+ smtp_pass: z.string().min(1),
69
+ from: z.string().email(),
70
+ to: z.array(z.string().email()).min(1),
71
+ on_failure: z.boolean().default(true),
72
+ on_success: z.boolean().default(false),
73
+ subject_prefix: z.string().default('[Qualyx]'),
74
+ });
75
+ export const TeamsConfigSchema = z.object({
76
+ webhook_url: z.string().url(),
77
+ on_failure: z.boolean().default(true),
78
+ on_success: z.boolean().default(false),
79
+ mention_on_failure: z.array(z.string()).optional(), // User emails to mention
80
+ });
81
+ export const JiraConfigSchema = z.object({
82
+ base_url: z.string().url(),
83
+ email: z.string().email(),
84
+ api_token: z.string().min(1),
85
+ project_key: z.string().min(1),
86
+ create_issues: z.boolean().default(true),
87
+ issue_type: z.string().default('Bug'),
88
+ labels: z.array(z.string()).optional(),
89
+ components: z.array(z.string()).optional(),
90
+ });
91
+ export const NotificationsSchema = z.object({
92
+ slack: SlackConfigSchema.optional(),
93
+ email: EmailConfigSchema.optional(),
94
+ teams: TeamsConfigSchema.optional(),
95
+ });
96
+ export const IntegrationsSchema = z.object({
97
+ jira: JiraConfigSchema.optional(),
98
+ });
99
+ export const QualyxConfigSchema = z.object({
100
+ organization: OrganizationSchema,
101
+ apps: z.array(AppSchema).min(1),
102
+ notifications: NotificationsSchema.optional(),
103
+ integrations: IntegrationsSchema.optional(),
104
+ });
105
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,75 @@
1
+ {
2
+ "name": "qualyx",
3
+ "version": "0.3.0",
4
+ "description": "AI-powered QA automation platform using Claude Code CLI and Playwright",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "bin": {
8
+ "qualyx": "dist/index.js"
9
+ },
10
+ "scripts": {
11
+ "build": "tsc",
12
+ "dev": "tsx src/index.ts",
13
+ "start": "node dist/index.js",
14
+ "test": "vitest",
15
+ "lint": "eslint src/",
16
+ "typecheck": "tsc --noEmit"
17
+ },
18
+ "keywords": [
19
+ "qa",
20
+ "testing",
21
+ "automation",
22
+ "ai",
23
+ "claude",
24
+ "playwright",
25
+ "e2e",
26
+ "end-to-end",
27
+ "natural-language",
28
+ "browser-testing"
29
+ ],
30
+ "author": "Koray Uysal",
31
+ "license": "MIT",
32
+ "repository": {
33
+ "type": "git",
34
+ "url": "git+https://github.com/korayuysal/qualyx.git"
35
+ },
36
+ "bugs": {
37
+ "url": "https://github.com/korayuysal/qualyx/issues"
38
+ },
39
+ "homepage": "https://github.com/korayuysal/qualyx#readme",
40
+ "files": [
41
+ "dist/cli",
42
+ "dist/core",
43
+ "dist/integrations",
44
+ "dist/reporters",
45
+ "dist/storage",
46
+ "dist/types",
47
+ "dist/index.js",
48
+ "dist/index.d.ts",
49
+ "dist/index.js.map",
50
+ "dist/index.d.ts.map",
51
+ "templates",
52
+ "README.md",
53
+ "LICENSE"
54
+ ],
55
+ "dependencies": {
56
+ "better-sqlite3": "^11.7.0",
57
+ "chalk": "^5.4.1",
58
+ "commander": "^12.1.0",
59
+ "handlebars": "^4.7.8",
60
+ "nodemailer": "^6.9.16",
61
+ "yaml": "^2.7.0",
62
+ "zod": "^3.24.1"
63
+ },
64
+ "devDependencies": {
65
+ "@types/better-sqlite3": "^7.6.12",
66
+ "@types/node": "^22.10.5",
67
+ "@types/nodemailer": "^6.4.17",
68
+ "tsx": "^4.19.2",
69
+ "typescript": "^5.7.3",
70
+ "vitest": "^2.1.8"
71
+ },
72
+ "engines": {
73
+ "node": ">=18.0.0"
74
+ }
75
+ }
@@ -0,0 +1,24 @@
1
+ # Qualyx Scheduled Test Crontab
2
+ # Generated: {{generatedAt}}
3
+ # Project: {{projectPath}}
4
+ #
5
+ # Install these entries with:
6
+ # crontab -e
7
+ # Or replace your crontab entirely:
8
+ # crontab /path/to/this/file
9
+ #
10
+ # Format: minute hour day-of-month month day-of-week command
11
+ # ┌───────────── minute (0 - 59)
12
+ # │ ┌───────────── hour (0 - 23)
13
+ # │ │ ┌───────────── day of month (1 - 31)
14
+ # │ │ │ ┌───────────── month (1 - 12)
15
+ # │ │ │ │ ┌───────────── day of week (0 - 6) (Sunday to Saturday)
16
+ # │ │ │ │ │
17
+ # * * * * * command
18
+
19
+ {{#each rules}}
20
+ # {{ruleName}} ({{appName}}) - {{formatCronDescription schedule}}
21
+ {{schedule}} cd '{{escapeShell ../projectPath}}' && qualyx run --rule '{{escapeShell ruleId}}' --report >> /tmp/qualyx-{{ruleId}}.log 2>&1
22
+
23
+ {{/each}}
24
+ # End of Qualyx scheduled tasks
@@ -0,0 +1,153 @@
1
+ # Qualyx Scheduled Tests - GitHub Actions Workflow
2
+ # Generated: {{generatedAt}}
3
+ # Organization: {{organizationName}}
4
+ #
5
+ # This workflow runs Qualyx tests on a schedule.
6
+ # Commit and push this file to enable scheduled runs.
7
+
8
+ name: Qualyx Scheduled Tests
9
+
10
+ on:
11
+ # Scheduled triggers for each unique schedule
12
+ schedule:
13
+ {{#each scheduleGroups}}
14
+ # {{#each rules}}{{ruleName}}{{#unless @last}}, {{/unless}}{{/each}}
15
+ - cron: '{{schedule}}'
16
+ {{/each}}
17
+
18
+ # Allow manual triggering with optional rule filter
19
+ workflow_dispatch:
20
+ inputs:
21
+ rule:
22
+ description: 'Specific rule ID to run (leave empty for all)'
23
+ required: false
24
+ type: string
25
+ app:
26
+ description: 'Specific app name to run (leave empty for all)'
27
+ required: false
28
+ type: string
29
+
30
+ env:
31
+ # Add your test credentials as repository secrets
32
+ # TEST_USER_EMAIL: $\{{ secrets.TEST_USER_EMAIL }}
33
+ # TEST_USER_PASSWORD: $\{{ secrets.TEST_USER_PASSWORD }}
34
+ ANTHROPIC_API_KEY: $\{{ secrets.ANTHROPIC_API_KEY }}
35
+
36
+ jobs:
37
+ test:
38
+ runs-on: ubuntu-latest
39
+ timeout-minutes: 30
40
+
41
+ steps:
42
+ - name: Checkout repository
43
+ uses: actions/checkout@v4
44
+
45
+ - name: Setup Node.js
46
+ uses: actions/setup-node@v4
47
+ with:
48
+ node-version: '20'
49
+ cache: 'npm'
50
+
51
+ - name: Install dependencies
52
+ run: npm ci
53
+
54
+ - name: Install Claude Code CLI
55
+ run: npm install -g @anthropic-ai/claude-code
56
+
57
+ - name: Install Playwright browsers
58
+ run: npx playwright install --with-deps chromium
59
+
60
+ - name: Determine which rule to run
61
+ id: determine-rule
62
+ run: |
63
+ # Check if this is a manual run with a specific rule
64
+ if [ -n "$\{{ github.event.inputs.rule }}" ]; then
65
+ echo "rule=$\{{ github.event.inputs.rule }}" >> $GITHUB_OUTPUT
66
+ echo "Running specific rule: $\{{ github.event.inputs.rule }}"
67
+ exit 0
68
+ fi
69
+
70
+ # Check if this is a manual run with a specific app
71
+ if [ -n "$\{{ github.event.inputs.app }}" ]; then
72
+ echo "app=$\{{ github.event.inputs.app }}" >> $GITHUB_OUTPUT
73
+ echo "Running all rules for app: $\{{ github.event.inputs.app }}"
74
+ exit 0
75
+ fi
76
+
77
+ # For scheduled runs, determine which rule based on cron
78
+ CURRENT_CRON="${\{ github.event.schedule }}"
79
+ echo "Current cron schedule: $CURRENT_CRON"
80
+
81
+ # Map cron schedules to rules
82
+ {{#each scheduleGroups}}
83
+ if [ "$CURRENT_CRON" = "{{schedule}}" ]; then
84
+ {{#if (gt rules.length 1)}}
85
+ # Multiple rules share this schedule - run all of them
86
+ echo "rules={{#each rules}}{{ruleId}}{{#unless @last}},{{/unless}}{{/each}}" >> $GITHUB_OUTPUT
87
+ {{else}}
88
+ echo "rule={{rules.[0].ruleId}}" >> $GITHUB_OUTPUT
89
+ {{/if}}
90
+ fi
91
+ {{/each}}
92
+
93
+ - name: Run Qualyx tests
94
+ run: |
95
+ RULE="${\{ steps.determine-rule.outputs.rule }}"
96
+ RULES="${\{ steps.determine-rule.outputs.rules }}"
97
+ APP="${\{ steps.determine-rule.outputs.app }}"
98
+
99
+ if [ -n "$RULE" ]; then
100
+ qualyx run --rule "$RULE" --report --report-dir ./qualyx-reports
101
+ elif [ -n "$RULES" ]; then
102
+ # Run multiple rules
103
+ IFS=',' read -ra RULE_ARRAY <<< "$RULES"
104
+ for rule in "${RULE_ARRAY[@]}"; do
105
+ echo "Running rule: $rule"
106
+ qualyx run --rule "$rule" --report --report-dir ./qualyx-reports || true
107
+ done
108
+ elif [ -n "$APP" ]; then
109
+ qualyx run --app "$APP" --report --report-dir ./qualyx-reports
110
+ else
111
+ # Fallback: run all tests
112
+ qualyx run --report --report-dir ./qualyx-reports
113
+ fi
114
+
115
+ - name: Upload test reports
116
+ uses: actions/upload-artifact@v4
117
+ if: always()
118
+ with:
119
+ name: qualyx-reports-$\{{ github.run_id }}
120
+ path: qualyx-reports/
121
+ retention-days: 30
122
+
123
+ - name: Upload screenshots (on failure)
124
+ uses: actions/upload-artifact@v4
125
+ if: failure()
126
+ with:
127
+ name: qualyx-screenshots-$\{{ github.run_id }}
128
+ path: qualyx-reports/screenshots/
129
+ retention-days: 14
130
+
131
+ # Individual jobs for each scheduled rule (alternative approach)
132
+ # Uncomment this section if you prefer separate jobs per rule
133
+
134
+ {{#each rules}}
135
+ # {{ruleId}}:
136
+ # runs-on: ubuntu-latest
137
+ # if: github.event.schedule == '{{schedule}}' || github.event.inputs.rule == '{{ruleId}}'
138
+ # steps:
139
+ # - uses: actions/checkout@v4
140
+ # - uses: actions/setup-node@v4
141
+ # with:
142
+ # node-version: '20'
143
+ # - run: npm ci
144
+ # - run: npm install -g @anthropic-ai/claude-code
145
+ # - run: npx playwright install --with-deps chromium
146
+ # - run: qualyx run --rule {{ruleId}} --report
147
+ # - uses: actions/upload-artifact@v4
148
+ # if: always()
149
+ # with:
150
+ # name: report-{{ruleId}}-$\{{ github.run_id }}
151
+ # path: qualyx-reports/
152
+
153
+ {{/each}}
@@ -0,0 +1,147 @@
1
+ # Test Execution: {{rule.name}}
2
+
3
+ ## Context
4
+ - **Application:** {{app.name}}
5
+ - **URL:** {{url}}
6
+ - **Test ID:** {{rule.id}}
7
+ - **Severity:** {{uppercase rule.severity}}
8
+ {{#if environment}}
9
+ - **Environment:** {{environment}}
10
+ {{/if}}
11
+
12
+ {{#if credentials}}
13
+ ## Credentials
14
+ {{#each credentials}}
15
+ - **{{@key}}:** {{this}}
16
+ {{/each}}
17
+ {{/if}}
18
+
19
+ {{#if previousAttempt}}
20
+ ## Previous Attempt Failed
21
+ **Error:** {{previousAttempt.error}}
22
+
23
+ {{#if previousAttempt.screenshot}}
24
+ A screenshot from the failure point has been captured. Please analyze it to understand what went wrong.
25
+ {{/if}}
26
+
27
+ {{#if previousAttempt.domSnippet}}
28
+ ### Relevant DOM at Failure Point
29
+ ```html
30
+ {{previousAttempt.domSnippet}}
31
+ ```
32
+ {{/if}}
33
+
34
+ **Instructions:** Please try a different approach or be more specific with element selectors.
35
+ {{/if}}
36
+
37
+ ## Test Instructions
38
+
39
+ Execute the following test steps using browser automation (Playwright):
40
+
41
+ {{#each rule.steps}}
42
+ {{stepNumber @index}}. {{formatStep this}}
43
+ {{/each}}
44
+
45
+ {{#if rule.validations}}
46
+ ## Validations to Check
47
+
48
+ After completing the steps above, verify the following:
49
+
50
+ {{#each rule.validations}}
51
+ - {{this}}
52
+ {{/each}}
53
+ {{/if}}
54
+
55
+ ## Screenshot Requirements
56
+
57
+ {{#if screenshotConfig}}
58
+ {{#if screenshotConfig.each_step}}
59
+ - **REQUIRED:** Take a screenshot after EACH step for debugging purposes
60
+ {{/if}}
61
+ {{#if screenshotConfig.on_failure}}
62
+ - **REQUIRED:** If any step fails, take a screenshot IMMEDIATELY at the failure point
63
+ {{/if}}
64
+ {{#if screenshotConfig.on_success}}
65
+ - **REQUIRED:** Take a final screenshot after all steps complete successfully
66
+ {{/if}}
67
+ {{else}}
68
+ - **REQUIRED:** Take a screenshot IMMEDIATELY if any step fails
69
+ - Include the screenshot in your response as base64-encoded data
70
+ {{/if}}
71
+
72
+ Screenshots should capture the full viewport and clearly show the state of the page at that moment.
73
+
74
+ ## Important Guidelines
75
+
76
+ 1. **Wait for page loads:** Always wait for navigation and content to load before interacting.
77
+ 2. **Be resilient:** If an exact selector doesn't work, try alternative approaches (text content, aria-labels, etc.).
78
+ 3. **Take screenshots:** Capture screenshots on failure, on success (if configured), or after each step (if debugging).
79
+ 4. **Handle dynamic content:** Wait for dynamic elements to appear before interacting.
80
+ 5. **Don't make assumptions:** If something is unclear, note it in the response rather than guessing.
81
+ 6. **Save screenshots:** When capturing screenshots, save them with descriptive names and include base64 data in your response.
82
+
83
+ {{#if app.auth}}
84
+ ## Authentication Details
85
+ - **Auth Type:** {{app.auth.type}}
86
+ {{#if app.auth.login_url}}
87
+ - **Login URL:** {{app.auth.login_url}}
88
+ {{/if}}
89
+ {{/if}}
90
+
91
+ {{#if collectMetrics}}
92
+ ## Performance Metrics Collection
93
+
94
+ **REQUIRED:** Collect the following performance metrics during test execution:
95
+
96
+ - **Page Load Time:** Time from navigation start to load event
97
+ - **DOM Content Loaded:** Time until DOM is fully parsed
98
+ - **First Contentful Paint (FCP):** Time until first content renders
99
+ - **Largest Contentful Paint (LCP):** Time until largest content element renders
100
+ - **Total Request Count:** Number of network requests made
101
+ - **Total Transfer Size:** Total bytes transferred
102
+
103
+ Use the browser's Performance API to collect these metrics:
104
+ ```javascript
105
+ const timing = performance.timing;
106
+ const entries = performance.getEntriesByType('paint');
107
+ const resources = performance.getEntriesByType('resource');
108
+ ```
109
+ {{/if}}
110
+
111
+ ## Expected Output Format
112
+
113
+ After executing the test, respond with a JSON object in the following format:
114
+
115
+ ```json
116
+ {
117
+ "status": "passed" | "failed",
118
+ "steps": [
119
+ {
120
+ "step": "Description of step",
121
+ "status": "passed" | "failed",
122
+ "timestamp": "ISO timestamp",
123
+ "duration": 1234,
124
+ "error": "Error message if failed"
125
+ }
126
+ ],
127
+ "validations": [
128
+ {
129
+ "validation": "What was validated",
130
+ "passed": true | false,
131
+ "details": "Additional details"
132
+ }
133
+ ],
134
+ "error": "Overall error message if test failed",
135
+ "screenshot": "base64 encoded screenshot if captured"{{#if collectMetrics}},
136
+ "performanceMetrics": {
137
+ "pageLoadTime": 1234,
138
+ "domContentLoaded": 567,
139
+ "firstContentfulPaint": 234,
140
+ "largestContentfulPaint": 890,
141
+ "totalRequestCount": 45,
142
+ "totalTransferSize": 1234567
143
+ }{{/if}}
144
+ }
145
+ ```
146
+
147
+ **Begin test execution now.**