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.
- package/LICENSE +21 -0
- package/README.md +523 -0
- package/dist/cli/commands/init.d.ts +6 -0
- package/dist/cli/commands/init.d.ts.map +1 -0
- package/dist/cli/commands/init.js +124 -0
- package/dist/cli/commands/init.js.map +1 -0
- package/dist/cli/commands/list.d.ts +3 -0
- package/dist/cli/commands/list.d.ts.map +1 -0
- package/dist/cli/commands/list.js +122 -0
- package/dist/cli/commands/list.js.map +1 -0
- package/dist/cli/commands/run.d.ts +12 -0
- package/dist/cli/commands/run.d.ts.map +1 -0
- package/dist/cli/commands/run.js +160 -0
- package/dist/cli/commands/run.js.map +1 -0
- package/dist/cli/commands/schedule.d.ts +19 -0
- package/dist/cli/commands/schedule.d.ts.map +1 -0
- package/dist/cli/commands/schedule.js +240 -0
- package/dist/cli/commands/schedule.js.map +1 -0
- package/dist/cli/commands/validate.d.ts +3 -0
- package/dist/cli/commands/validate.d.ts.map +1 -0
- package/dist/cli/commands/validate.js +47 -0
- package/dist/cli/commands/validate.js.map +1 -0
- package/dist/cli/index.d.ts +3 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +194 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/core/claude-runner.d.ts +23 -0
- package/dist/core/claude-runner.d.ts.map +1 -0
- package/dist/core/claude-runner.js +196 -0
- package/dist/core/claude-runner.js.map +1 -0
- package/dist/core/config-loader.d.ts +137 -0
- package/dist/core/config-loader.d.ts.map +1 -0
- package/dist/core/config-loader.js +239 -0
- package/dist/core/config-loader.js.map +1 -0
- package/dist/core/executor.d.ts +75 -0
- package/dist/core/executor.d.ts.map +1 -0
- package/dist/core/executor.js +337 -0
- package/dist/core/executor.js.map +1 -0
- package/dist/core/index.d.ts +6 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +7 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/prompt-builder.d.ts +24 -0
- package/dist/core/prompt-builder.d.ts.map +1 -0
- package/dist/core/prompt-builder.js +145 -0
- package/dist/core/prompt-builder.js.map +1 -0
- package/dist/core/retry-handler.d.ts +42 -0
- package/dist/core/retry-handler.d.ts.map +1 -0
- package/dist/core/retry-handler.js +126 -0
- package/dist/core/retry-handler.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +16 -0
- package/dist/index.js.map +1 -0
- package/dist/integrations/email.d.ts +38 -0
- package/dist/integrations/email.d.ts.map +1 -0
- package/dist/integrations/email.js +216 -0
- package/dist/integrations/email.js.map +1 -0
- package/dist/integrations/index.d.ts +5 -0
- package/dist/integrations/index.d.ts.map +1 -0
- package/dist/integrations/index.js +5 -0
- package/dist/integrations/index.js.map +1 -0
- package/dist/integrations/jira.d.ts +68 -0
- package/dist/integrations/jira.d.ts.map +1 -0
- package/dist/integrations/jira.js +288 -0
- package/dist/integrations/jira.js.map +1 -0
- package/dist/integrations/slack.d.ts +66 -0
- package/dist/integrations/slack.d.ts.map +1 -0
- package/dist/integrations/slack.js +192 -0
- package/dist/integrations/slack.js.map +1 -0
- package/dist/integrations/teams.d.ts +72 -0
- package/dist/integrations/teams.d.ts.map +1 -0
- package/dist/integrations/teams.js +197 -0
- package/dist/integrations/teams.js.map +1 -0
- package/dist/reporters/console.d.ts +83 -0
- package/dist/reporters/console.d.ts.map +1 -0
- package/dist/reporters/console.js +299 -0
- package/dist/reporters/console.js.map +1 -0
- package/dist/reporters/html.d.ts +29 -0
- package/dist/reporters/html.d.ts.map +1 -0
- package/dist/reporters/html.js +105 -0
- package/dist/reporters/html.js.map +1 -0
- package/dist/storage/results.d.ts +61 -0
- package/dist/storage/results.d.ts.map +1 -0
- package/dist/storage/results.js +111 -0
- package/dist/storage/results.js.map +1 -0
- package/dist/storage/sqlite.d.ts +70 -0
- package/dist/storage/sqlite.d.ts.map +1 -0
- package/dist/storage/sqlite.js +240 -0
- package/dist/storage/sqlite.js.map +1 -0
- package/dist/types/index.d.ts +1239 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +105 -0
- package/dist/types/index.js.map +1 -0
- package/package.json +75 -0
- package/templates/crontab.hbs +24 -0
- package/templates/github-schedule.yml.hbs +153 -0
- package/templates/prompt.md.hbs +147 -0
- package/templates/report.html.hbs +423 -0
- 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":"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"}
|
|
@@ -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":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,+DAA+D;AAC/D,2CAA2C;AAC3C,+DAA+D;AAE/D,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,CAAC,KAAK,CAAC;IAChC,CAAC,CAAC,MAAM,EAAE;IACV,CAAC,CAAC,MAAM,CAAC;QACP,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE;QAClB,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;QAC3B,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;KAC/B,CAAC;CACH,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,CAAC,MAAM,CAAC;IACjC,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACrB,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACvB,QAAQ,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC;IACzE,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE;IACzC,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IACjC,WAAW,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE;IAC3C,UAAU,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE;IAC1C,SAAS,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,QAAQ,EAAE;IAC3C,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,EAAE,iCAAiC;IAClE,UAAU,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE,EAAE,iCAAiC;CACtE,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,CAAC,MAAM,CAAC;IACjC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,YAAY,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC;IACjF,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE;IAC5C,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE;CACvC,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC9C,UAAU,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC;IACrC,UAAU,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC;IACtC,SAAS,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC;CACtC,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,CAAC,MAAM,CAAC;IAChC,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACvB,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE;IACrB,YAAY,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,CAAC,QAAQ,EAAE;IACnD,IAAI,EAAE,UAAU,CAAC,QAAQ,EAAE;IAC3B,WAAW,EAAE,uBAAuB,CAAC,QAAQ,EAAE;IAC/C,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE,EAAE,kCAAkC;IACzE,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;CAClC,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,0BAA0B,GAAG,CAAC,CAAC,MAAM,CAAC;IACjD,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC;IAC7C,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;IAC5C,QAAQ,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC;CACpC,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,CAAC,MAAM,CAAC;IACzC,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACvB,QAAQ,EAAE,0BAA0B,CAAC,QAAQ,EAAE;CAChD,CAAC,CAAC;AAEH,+DAA+D;AAC/D,qCAAqC;AACrC,+DAA+D;AAE/D,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,CAAC,MAAM,CAAC;IACxC,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAC9B,UAAU,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC;IACrC,UAAU,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC;IACtC,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,EAAE,4CAA4C;IAC5E,kBAAkB,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE,EAAE,iCAAiC;CACtF,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,CAAC,MAAM,CAAC;IACxC,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAC5B,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC;IAClC,WAAW,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,sCAAsC;IAC/E,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAC5B,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAC5B,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE;IACxB,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IACtC,UAAU,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC;IACrC,UAAU,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC;IACtC,cAAc,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,UAAU,CAAC;CAC/C,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,CAAC,MAAM,CAAC;IACxC,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE;IAC7B,UAAU,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC;IACrC,UAAU,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC;IACtC,kBAAkB,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE,EAAE,yBAAyB;CAC9E,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,CAAC,MAAM,CAAC;IACvC,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE;IAC1B,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE;IACzB,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAC5B,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAC9B,aAAa,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC;IACxC,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC;IACrC,MAAM,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE;IACtC,UAAU,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE;CAC3C,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC1C,KAAK,EAAE,iBAAiB,CAAC,QAAQ,EAAE;IACnC,KAAK,EAAE,iBAAiB,CAAC,QAAQ,EAAE;IACnC,KAAK,EAAE,iBAAiB,CAAC,QAAQ,EAAE;CACpC,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,CAAC,MAAM,CAAC;IACzC,IAAI,EAAE,gBAAgB,CAAC,QAAQ,EAAE;CAClC,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,CAAC,MAAM,CAAC;IACzC,YAAY,EAAE,kBAAkB;IAChC,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IAC/B,aAAa,EAAE,mBAAmB,CAAC,QAAQ,EAAE;IAC7C,YAAY,EAAE,kBAAkB,CAAC,QAAQ,EAAE;CAC5C,CAAC,CAAC"}
|
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.**
|