synthra 0.1.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 (302) hide show
  1. checksums.yaml +7 -0
  2. data/.rspec +4 -0
  3. data/.rubocop.yml +40 -0
  4. data/.yardopts +18 -0
  5. data/ACCESS_DOCS.md +116 -0
  6. data/ADVANCED_FEATURES_SUMMARY.md +245 -0
  7. data/CHANGELOG.md +498 -0
  8. data/CODE_OF_CONDUCT.md +122 -0
  9. data/CONTRIBUTING.md +307 -0
  10. data/DOCUMENTATION.md +204 -0
  11. data/DOCUMENTATION_GUIDE.md +194 -0
  12. data/LICENSE +22 -0
  13. data/README.md +1458 -0
  14. data/Rakefile +128 -0
  15. data/benchmark/README.md +591 -0
  16. data/benchmark/batch_generation.rb +63 -0
  17. data/benchmark/engine_comparison.rb +295 -0
  18. data/benchmark/single_record.rb +108 -0
  19. data/benchmark/streaming.rb +74 -0
  20. data/docs/ACTIVERECORD_INFERENCE.md +524 -0
  21. data/docs/API_SERVER.md +278 -0
  22. data/docs/CONFIG_FILE.md +315 -0
  23. data/docs/DATA_CONTRACTS.md +312 -0
  24. data/docs/ENHANCED_REPL.md +304 -0
  25. data/docs/FACTORY_BOT.md +271 -0
  26. data/docs/GITHUB_ACTION.md +420 -0
  27. data/docs/GRAPHQL_EXPORT.md +303 -0
  28. data/docs/GRAPHQL_FEDERATION.md +651 -0
  29. data/docs/HOW_TO_GENERATE_DOCS.md +252 -0
  30. data/docs/LSP.md +189 -0
  31. data/docs/MIGRATION_GENERATOR.md +547 -0
  32. data/docs/MOCK_SERVER.md +280 -0
  33. data/docs/NATIVE_ENGINE.md +298 -0
  34. data/docs/OPENAPI_EXPORT.md +252 -0
  35. data/docs/PERFORMANCE_MODE.md +228 -0
  36. data/docs/PERSONAS.md +547 -0
  37. data/docs/PROPERTY_TESTING.md +284 -0
  38. data/docs/PROTOBUF_EXPORT.md +276 -0
  39. data/docs/QUALITY_METRICS.md +555 -0
  40. data/docs/QUICK_REFERENCE.md +88 -0
  41. data/docs/RAILS_ENGINE.md +404 -0
  42. data/docs/RAILS_INTEGRATION.md +454 -0
  43. data/docs/README.md +175 -0
  44. data/docs/REPL_QUICK_REFERENCE.md +149 -0
  45. data/docs/RUST_INTEGRATION_GUIDE.md +1376 -0
  46. data/docs/SCENARIOS.md +576 -0
  47. data/docs/SECURITY_TESTING.md +318 -0
  48. data/docs/SNAPSHOT_TESTING.md +308 -0
  49. data/docs/STRING_TEXT_TYPES_REFERENCE.md +512 -0
  50. data/docs/TERRAFORM_EXPORT.md +447 -0
  51. data/docs/TIME_TRAVEL.md +507 -0
  52. data/docs/USAGE_GUIDE.md +980 -0
  53. data/docs/WEBHOOK_SIMULATOR.md +579 -0
  54. data/docs/advanced_features.md +183 -0
  55. data/docs/api_reference.md +153 -0
  56. data/docs/behaviors.md +138 -0
  57. data/docs/best_practices.md +191 -0
  58. data/docs/dsl_reference.md +172 -0
  59. data/docs/examples.md +162 -0
  60. data/docs/generation_modes.md +125 -0
  61. data/docs/getting_started.md +92 -0
  62. data/docs/index.html +177 -0
  63. data/docs/strategic/CLOUD_REGISTRY_ARCHITECTURE.md +268 -0
  64. data/docs/strategic/SIMD_OPTIMIZATION_STRATEGY.md +153 -0
  65. data/docs/troubleshooting.md +215 -0
  66. data/docs/type_reference.md +224 -0
  67. data/examples/hostile_mode_demo.rb +64 -0
  68. data/exe/synthra +6 -0
  69. data/ext/synthra_native/Cargo.lock +972 -0
  70. data/ext/synthra_native/Cargo.toml +46 -0
  71. data/ext/synthra_native/extconf.rb +41 -0
  72. data/ext/synthra_native/src/generator.rs +397 -0
  73. data/ext/synthra_native/src/lib.rs +229 -0
  74. data/ext/synthra_native/src/types.rs +1485 -0
  75. data/lib/generators/synthra/install_generator.rb +86 -0
  76. data/lib/generators/synthra/templates/api_response.dsl +15 -0
  77. data/lib/generators/synthra/templates/fake_data.rake +116 -0
  78. data/lib/generators/synthra/templates/synthra.yml +31 -0
  79. data/lib/generators/synthra/templates/synthra_support.rb +19 -0
  80. data/lib/generators/synthra/templates/user.dsl +11 -0
  81. data/lib/synthra/activerecord_inference.rb +394 -0
  82. data/lib/synthra/api.rb +381 -0
  83. data/lib/synthra/api_server.rb +718 -0
  84. data/lib/synthra/behaviors/applicator.rb +165 -0
  85. data/lib/synthra/behaviors/base.rb +155 -0
  86. data/lib/synthra/behaviors/close_connection.rb +60 -0
  87. data/lib/synthra/behaviors/deprecated.rb +100 -0
  88. data/lib/synthra/behaviors/failure.rb +69 -0
  89. data/lib/synthra/behaviors/latency.rb +103 -0
  90. data/lib/synthra/behaviors/partial_data.rb +83 -0
  91. data/lib/synthra/behaviors/randomize_order.rb +74 -0
  92. data/lib/synthra/behaviors/registry.rb +238 -0
  93. data/lib/synthra/behaviors/simulate_error.rb +79 -0
  94. data/lib/synthra/cli/commands/base.rb +105 -0
  95. data/lib/synthra/cli/commands/diff.rb +227 -0
  96. data/lib/synthra/cli/commands/docs.rb +67 -0
  97. data/lib/synthra/cli/commands/export.rb +150 -0
  98. data/lib/synthra/cli/commands/generate.rb +72 -0
  99. data/lib/synthra/cli/commands/import.rb +80 -0
  100. data/lib/synthra/cli/commands/lint.rb +53 -0
  101. data/lib/synthra/cli/commands/live.rb +57 -0
  102. data/lib/synthra/cli/commands/seed.rb +99 -0
  103. data/lib/synthra/cli/commands/validate.rb +28 -0
  104. data/lib/synthra/cli.rb +2471 -0
  105. data/lib/synthra/config_file.rb +129 -0
  106. data/lib/synthra/configuration.rb +281 -0
  107. data/lib/synthra/contracts_registry.rb +408 -0
  108. data/lib/synthra/database_seeder.rb +268 -0
  109. data/lib/synthra/deterministic_ids.rb +218 -0
  110. data/lib/synthra/documentation_generator.rb +414 -0
  111. data/lib/synthra/engine.rb +251 -0
  112. data/lib/synthra/errors.rb +1169 -0
  113. data/lib/synthra/export/base.rb +85 -0
  114. data/lib/synthra/export/csv.rb +101 -0
  115. data/lib/synthra/export/graphql.rb +266 -0
  116. data/lib/synthra/export/graphql_federation.rb +377 -0
  117. data/lib/synthra/export/graphviz.rb +258 -0
  118. data/lib/synthra/export/javascript.rb +327 -0
  119. data/lib/synthra/export/json_data.rb +61 -0
  120. data/lib/synthra/export/json_schema.rb +290 -0
  121. data/lib/synthra/export/openapi.rb +514 -0
  122. data/lib/synthra/export/protobuf.rb +483 -0
  123. data/lib/synthra/export/python.rb +560 -0
  124. data/lib/synthra/export/sql.rb +381 -0
  125. data/lib/synthra/export/sql_insert.rb +152 -0
  126. data/lib/synthra/export/terraform.rb +501 -0
  127. data/lib/synthra/export/type_mapping.rb +389 -0
  128. data/lib/synthra/export/typescript.rb +300 -0
  129. data/lib/synthra/export/xml_data.rb +104 -0
  130. data/lib/synthra/export/yaml_data.rb +56 -0
  131. data/lib/synthra/export.rb +404 -0
  132. data/lib/synthra/factory_bot_integration.rb +157 -0
  133. data/lib/synthra/field.rb +440 -0
  134. data/lib/synthra/functions/registry.rb +104 -0
  135. data/lib/synthra/generator/context.rb +372 -0
  136. data/lib/synthra/generator/engine.rb +336 -0
  137. data/lib/synthra/generator/faker_adapter.rb +425 -0
  138. data/lib/synthra/generator/modes.rb +444 -0
  139. data/lib/synthra/generator/resolver.rb +256 -0
  140. data/lib/synthra/generator/rng.rb +273 -0
  141. data/lib/synthra/generator/streamer.rb +63 -0
  142. data/lib/synthra/generator/uniqueness.rb +118 -0
  143. data/lib/synthra/initializer.rb +97 -0
  144. data/lib/synthra/limits.rb +279 -0
  145. data/lib/synthra/live_preview.rb +518 -0
  146. data/lib/synthra/loader_config.rb +78 -0
  147. data/lib/synthra/lsp/server.rb +689 -0
  148. data/lib/synthra/migration_generator.rb +301 -0
  149. data/lib/synthra/mixin.rb +174 -0
  150. data/lib/synthra/mock_server.rb +458 -0
  151. data/lib/synthra/native_engine.rb +304 -0
  152. data/lib/synthra/openapi_importer.rb +228 -0
  153. data/lib/synthra/output/json_formatter.rb +40 -0
  154. data/lib/synthra/output/ndjson_formatter.rb +55 -0
  155. data/lib/synthra/parser/ast.rb +1287 -0
  156. data/lib/synthra/parser/lexer.rb +1152 -0
  157. data/lib/synthra/parser/parser.rb +1664 -0
  158. data/lib/synthra/parser/tokens.rb +461 -0
  159. data/lib/synthra/performance_mode.rb +364 -0
  160. data/lib/synthra/personas.rb +397 -0
  161. data/lib/synthra/property_testing.rb +172 -0
  162. data/lib/synthra/quality_metrics.rb +405 -0
  163. data/lib/synthra/rails_test_helper.rb +248 -0
  164. data/lib/synthra/registry.rb +533 -0
  165. data/lib/synthra/relationships.rb +193 -0
  166. data/lib/synthra/repl/enhanced_repl.rb +607 -0
  167. data/lib/synthra/repl/formatter.rb +191 -0
  168. data/lib/synthra/scenarios.rb +423 -0
  169. data/lib/synthra/schema.rb +605 -0
  170. data/lib/synthra/schema_inheritance.rb +104 -0
  171. data/lib/synthra/schema_versioning.rb +212 -0
  172. data/lib/synthra/snapshot_testing.rb +199 -0
  173. data/lib/synthra/time_travel.rb +338 -0
  174. data/lib/synthra/type_definitions.rb +274 -0
  175. data/lib/synthra/types/address_location/addresses.rb +125 -0
  176. data/lib/synthra/types/address_location/airports.rb +200 -0
  177. data/lib/synthra/types/address_location/banks_hospitals.rb +207 -0
  178. data/lib/synthra/types/address_location/locations.rb +406 -0
  179. data/lib/synthra/types/base.rb +48 -0
  180. data/lib/synthra/types/commerce_products/commerce.rb +119 -0
  181. data/lib/synthra/types/commerce_products/companies.rb +71 -0
  182. data/lib/synthra/types/commerce_products/construction.rb +126 -0
  183. data/lib/synthra/types/commerce_products/products.rb +205 -0
  184. data/lib/synthra/types/core/collections.rb +513 -0
  185. data/lib/synthra/types/core/defaults.rb +76 -0
  186. data/lib/synthra/types/core/enums.rb +102 -0
  187. data/lib/synthra/types/core/identifiers.rb +445 -0
  188. data/lib/synthra/types/core/primitives.rb +586 -0
  189. data/lib/synthra/types/core/references.rb +466 -0
  190. data/lib/synthra/types/core/sequences.rb +304 -0
  191. data/lib/synthra/types/crypto/crypto.rb +162 -0
  192. data/lib/synthra/types/date_time/dates.rb +387 -0
  193. data/lib/synthra/types/finance_banking/banking.rb +424 -0
  194. data/lib/synthra/types/finance_banking/credit_cards.rb +24 -0
  195. data/lib/synthra/types/finance_banking/identifiers.rb +93 -0
  196. data/lib/synthra/types/formula.rb +184 -0
  197. data/lib/synthra/types/health_medical/medical.rb +150 -0
  198. data/lib/synthra/types/hostile_payloads.rb +122 -0
  199. data/lib/synthra/types/json_array.rb +51 -0
  200. data/lib/synthra/types/media_entertainment/media.rb +62 -0
  201. data/lib/synthra/types/naughty_string.rb +30 -0
  202. data/lib/synthra/types/personal_names/chinese.rb +41 -0
  203. data/lib/synthra/types/personal_names/identifiers.rb +187 -0
  204. data/lib/synthra/types/personal_names/names.rb +246 -0
  205. data/lib/synthra/types/personal_names/national_id.rb +89 -0
  206. data/lib/synthra/types/personal_names/titles_suffixes.rb +41 -0
  207. data/lib/synthra/types/regex.rb +248 -0
  208. data/lib/synthra/types/registry.rb +182 -0
  209. data/lib/synthra/types/repeating_element.rb +50 -0
  210. data/lib/synthra/types/scenario.rb +29 -0
  211. data/lib/synthra/types/technology_internet/apps.rb +67 -0
  212. data/lib/synthra/types/technology_internet/communication.rb +162 -0
  213. data/lib/synthra/types/technology_internet/devices.rb +80 -0
  214. data/lib/synthra/types/technology_internet/formats.rb +139 -0
  215. data/lib/synthra/types/technology_internet/networking.rb +143 -0
  216. data/lib/synthra/types/template.rb +92 -0
  217. data/lib/synthra/types/text_content/business.rb +128 -0
  218. data/lib/synthra/types/text_content/colors.rb +70 -0
  219. data/lib/synthra/types/text_content/misc.rb +237 -0
  220. data/lib/synthra/types/text_content/security.rb +130 -0
  221. data/lib/synthra/types/text_content/text_generation.rb +532 -0
  222. data/lib/synthra/types/travel/travel.rb +150 -0
  223. data/lib/synthra/utils/string_distance.rb +133 -0
  224. data/lib/synthra/validator/dsl_validator.rb +339 -0
  225. data/lib/synthra/validator/path_validator.rb +615 -0
  226. data/lib/synthra/version.rb +35 -0
  227. data/lib/synthra/webhook_simulator.rb +341 -0
  228. data/lib/synthra.rb +259 -0
  229. data/schemas/address.dsl +16 -0
  230. data/schemas/api_response.dsl +8 -0
  231. data/schemas/error_payload.dsl +9 -0
  232. data/schemas/order.dsl +10 -0
  233. data/schemas/order_item.dsl +8 -0
  234. data/schemas/payment.dsl +11 -0
  235. data/schemas/social_post.dsl +13 -0
  236. data/schemas/user.dsl +10 -0
  237. data/scripts/batch_fix_all.rb +96 -0
  238. data/scripts/delete_old_files.rb +32 -0
  239. data/scripts/fix_all_grouped_files.rb +137 -0
  240. data/scripts/fix_all_indentation.rb +48 -0
  241. data/scripts/fix_all_syntax.rb +124 -0
  242. data/scripts/fix_grouped_files.rb +184 -0
  243. data/scripts/fix_syntax_errors.rb +108 -0
  244. data/scripts/group_domain_types.rb +112 -0
  245. data/scripts/group_domain_types_fixed.rb +150 -0
  246. data/scripts/merge_domains_to_one_file.rb +68 -0
  247. data/scripts/move_existing_types.rb +130 -0
  248. data/scripts/split_grouped_types.rb +142 -0
  249. data/tech_docs/README.md +134 -0
  250. data/tech_docs/advanced/streaming.md +405 -0
  251. data/tech_docs/advanced/thread_safety.md +253 -0
  252. data/tech_docs/api/overview.md +485 -0
  253. data/tech_docs/appendices/type_chart.md +193 -0
  254. data/tech_docs/basic_concepts.md +383 -0
  255. data/tech_docs/behaviors/overview.md +346 -0
  256. data/tech_docs/dsl/complex_types.md +790 -0
  257. data/tech_docs/dsl/core_types.md +464 -0
  258. data/tech_docs/dsl/datetime_types.md +325 -0
  259. data/tech_docs/dsl/field_modifiers.md +414 -0
  260. data/tech_docs/dsl/grammar.md +431 -0
  261. data/tech_docs/dsl/schema_definition.md +399 -0
  262. data/tech_docs/export/README.md +276 -0
  263. data/tech_docs/installation.md +273 -0
  264. data/tech_docs/integration/ci_cd.md +707 -0
  265. data/tech_docs/integration/ci_cd_guide.md +579 -0
  266. data/tech_docs/integration/factory_bot.md +485 -0
  267. data/tech_docs/integration/rails.md +630 -0
  268. data/tech_docs/integration/rspec.md +449 -0
  269. data/tech_docs/modes/overview.md +350 -0
  270. data/tech_docs/performance/NATIVE_RUST_EXTENSION.md +1270 -0
  271. data/tech_docs/performance/OPTIMIZATION_GUIDE.md +901 -0
  272. data/tech_docs/quick_start.md +256 -0
  273. data/tech_docs/templates/README.md +805 -0
  274. data/tech_docs/tutorials/advanced.md +371 -0
  275. data/tech_docs/tutorials/getting_started.md +189 -0
  276. data/tech_docs/tutorials/intermediate.md +231 -0
  277. data/tech_docs/tutorials/template_gallery.md +569 -0
  278. data/tech_example/01_basic_usage.rb +238 -0
  279. data/tech_example/02_types_demo.rb +336 -0
  280. data/tech_example/04_cli_usage.md +429 -0
  281. data/tech_example/05_database_seeding.rb +283 -0
  282. data/tech_example/07_rspec_integration.rb +359 -0
  283. data/tech_example/10_custom_types.rb +387 -0
  284. data/tech_example/12_behaviors.rb +372 -0
  285. data/tech_example/13_twitter_dm_example.rb +120 -0
  286. data/tech_example/14_exact_json_structure.rb +253 -0
  287. data/tech_example/16_lsp_server.rb +56 -0
  288. data/tech_example/17_property_testing.rb +92 -0
  289. data/tech_example/18_enhanced_repl.rb +120 -0
  290. data/tech_example/19_security_fuzzing.rb +145 -0
  291. data/tech_example/NEW_FEATURES.md +169 -0
  292. data/tech_example/README.md +118 -0
  293. data/tech_example/schemas/api_response.dsl +123 -0
  294. data/tech_example/schemas/ecommerce.dsl +121 -0
  295. data/tech_example/schemas/twitter_dm.dsl +109 -0
  296. data/tech_example/schemas/user.dsl +36 -0
  297. data/vscode-extension/README.md +246 -0
  298. data/vscode-extension/language-configuration.json +31 -0
  299. data/vscode-extension/package.json +55 -0
  300. data/vscode-extension/snippets/fakedatadsl.json +198 -0
  301. data/vscode-extension/syntaxes/fakedatadsl.tmLanguage.json +128 -0
  302. metadata +478 -0
data/docs/PERSONAS.md ADDED
@@ -0,0 +1,547 @@
1
+ # Personas: Named Data Profiles
2
+
3
+ Personas let you define **named data profiles** that combine generation modes, field overrides, and behaviors into reusable configurations. Instead of thinking in technical terms like "edge mode" or "hostile mode," think in user archetypes: "happy path user," "free tier customer," or "problematic account."
4
+
5
+ ## Quick Start
6
+
7
+ ```ruby
8
+ # Define personas
9
+ FakeDataDSL::Personas.define(:happy_path) do
10
+ mode :random
11
+ override "User", email_verified: true, subscription: "premium"
12
+ end
13
+
14
+ FakeDataDSL::Personas.define(:problematic) do
15
+ mode :hostile
16
+ override "User", name: "'; DROP TABLE users; --"
17
+ end
18
+
19
+ # Use personas
20
+ user = FakeDataDSL.as(:happy_path) { FakeDataDSL.generate("User") }
21
+ hacker = FakeDataDSL.as(:problematic) { FakeDataDSL.generate("User") }
22
+ ```
23
+
24
+ ## Defining Personas
25
+
26
+ ### Basic Persona
27
+
28
+ ```ruby
29
+ FakeDataDSL::Personas.define(:standard_user) do
30
+ mode :random
31
+ end
32
+ ```
33
+
34
+ ### With Overrides
35
+
36
+ ```ruby
37
+ FakeDataDSL::Personas.define(:premium_customer) do
38
+ mode :random
39
+
40
+ override "User",
41
+ subscription: "premium",
42
+ email_verified: true,
43
+ created_at: 1.year.ago
44
+
45
+ override "Account",
46
+ plan: "enterprise",
47
+ seats: 50
48
+ end
49
+ ```
50
+
51
+ ### With Behaviors
52
+
53
+ ```ruby
54
+ FakeDataDSL::Personas.define(:slow_connection) do
55
+ mode :random
56
+
57
+ behavior :latency, min: 500, max: 2000 # 500-2000ms delays
58
+ behavior :timeout, probability: 0.1 # 10% timeout rate
59
+ end
60
+ ```
61
+
62
+ ## Built-in Personas
63
+
64
+ FakeDataDSL includes several built-in personas:
65
+
66
+ ### :happy_path
67
+
68
+ Standard, valid data that represents the ideal user journey.
69
+
70
+ ```ruby
71
+ FakeDataDSL.as(:happy_path) do
72
+ user = FakeDataDSL.generate("User")
73
+ # All fields valid, all required fields present
74
+ # Represents a "normal" user
75
+ end
76
+ ```
77
+
78
+ ### :edge_case
79
+
80
+ Data at the boundaries of valid ranges.
81
+
82
+ ```ruby
83
+ FakeDataDSL.as(:edge_case) do
84
+ user = FakeDataDSL.generate("User")
85
+ # age might be 0 or 150
86
+ # name might be 1 character or 255 characters
87
+ # Tests boundary conditions
88
+ end
89
+ ```
90
+
91
+ ### :minimal
92
+
93
+ Only required fields, everything else nil/empty.
94
+
95
+ ```ruby
96
+ FakeDataDSL.as(:minimal) do
97
+ user = FakeDataDSL.generate("User")
98
+ # Only id, name, email (required fields)
99
+ # All optional fields are nil
100
+ end
101
+ ```
102
+
103
+ ### :maximal
104
+
105
+ All fields populated, arrays at max length.
106
+
107
+ ```ruby
108
+ FakeDataDSL.as(:maximal) do
109
+ user = FakeDataDSL.generate("User")
110
+ # All optional fields populated
111
+ # Arrays at maximum allowed length
112
+ end
113
+ ```
114
+
115
+ ### :hacker
116
+
117
+ Malicious input attempting to exploit vulnerabilities.
118
+
119
+ ```ruby
120
+ FakeDataDSL.as(:hacker) do
121
+ user = FakeDataDSL.generate("User")
122
+ # SQL injection in text fields
123
+ # XSS attempts in HTML-allowed fields
124
+ # Path traversal in file fields
125
+ end
126
+ ```
127
+
128
+ ### :international
129
+
130
+ Data with international characters and formats.
131
+
132
+ ```ruby
133
+ FakeDataDSL.as(:international) do
134
+ user = FakeDataDSL.generate("User")
135
+ # Names in various scripts (Chinese, Arabic, Cyrillic)
136
+ # International phone formats
137
+ # Non-ASCII email addresses
138
+ end
139
+ ```
140
+
141
+ ## Using Personas
142
+
143
+ ### Block Syntax
144
+
145
+ ```ruby
146
+ FakeDataDSL.as(:premium_customer) do
147
+ user = FakeDataDSL.generate("User")
148
+ orders = FakeDataDSL.generate_many("Order", 5)
149
+ end
150
+ ```
151
+
152
+ ### Method Chaining
153
+
154
+ ```ruby
155
+ user = FakeDataDSL.generate("User").as(:happy_path)
156
+ orders = FakeDataDSL.generate_many("Order", 10).as(:edge_case)
157
+ ```
158
+
159
+ ### In Tests
160
+
161
+ ```ruby
162
+ RSpec.describe "User Registration" do
163
+ FakeDataDSL::Personas.each do |persona_name|
164
+ context "as #{persona_name}" do
165
+ let(:user_data) { FakeDataDSL.as(persona_name) { generate("User") } }
166
+
167
+ it "handles registration" do
168
+ result = UserRegistration.call(user_data)
169
+ # Verify behavior for each persona
170
+ end
171
+ end
172
+ end
173
+ end
174
+ ```
175
+
176
+ ## Advanced Configuration
177
+
178
+ ### Persona Inheritance
179
+
180
+ ```ruby
181
+ FakeDataDSL::Personas.define(:base_customer) do
182
+ mode :random
183
+ override "User", role: "customer"
184
+ end
185
+
186
+ FakeDataDSL::Personas.define(:new_customer, extends: :base_customer) do
187
+ override "User",
188
+ created_at: 1.day.ago,
189
+ first_purchase: nil
190
+ end
191
+
192
+ FakeDataDSL::Personas.define(:loyal_customer, extends: :base_customer) do
193
+ override "User",
194
+ created_at: 2.years.ago,
195
+ purchase_count: 50,
196
+ loyalty_tier: "gold"
197
+ end
198
+ ```
199
+
200
+ ### Conditional Overrides
201
+
202
+ ```ruby
203
+ FakeDataDSL::Personas.define(:seasonal_shopper) do
204
+ mode :random
205
+
206
+ override "User" do |context|
207
+ if context[:month].in?([11, 12]) # Holiday season
208
+ { purchase_frequency: "high", budget: 1000..5000 }
209
+ else
210
+ { purchase_frequency: "low", budget: 50..200 }
211
+ end
212
+ end
213
+ end
214
+ ```
215
+
216
+ ### Dynamic Personas
217
+
218
+ ```ruby
219
+ FakeDataDSL::Personas.define(:load_test) do |scale: 1|
220
+ mode :random
221
+
222
+ override "User",
223
+ connections: 10 * scale,
224
+ requests_per_minute: 100 * scale
225
+ end
226
+
227
+ # Usage
228
+ FakeDataDSL.as(:load_test, scale: 10) { ... }
229
+ ```
230
+
231
+ ## YAML Configuration
232
+
233
+ Define personas in configuration files:
234
+
235
+ ```yaml
236
+ # config/fake_data_dsl.yml
237
+ personas:
238
+ happy_path:
239
+ mode: random
240
+ overrides:
241
+ User:
242
+ email_verified: true
243
+ subscription: premium
244
+
245
+ free_user:
246
+ mode: random
247
+ overrides:
248
+ User:
249
+ subscription: free
250
+ created_at: 2.years.ago
251
+
252
+ problematic:
253
+ mode: edge
254
+ overrides:
255
+ User:
256
+ name: "'; DROP TABLE users; --"
257
+ email: test@test.test
258
+
259
+ international:
260
+ mode: random
261
+ locale: multi
262
+ overrides:
263
+ User:
264
+ name_locale: [zh, ar, ru, ja, ko]
265
+
266
+ # Environment-specific
267
+ test:
268
+ default_persona: happy_path
269
+
270
+ development:
271
+ default_persona: random
272
+ ```
273
+
274
+ ## Persona Combinations
275
+
276
+ ### Multiple Personas
277
+
278
+ ```ruby
279
+ # Combine persona traits
280
+ FakeDataDSL.as(:premium_customer, :international) do
281
+ user = FakeDataDSL.generate("User")
282
+ # Premium subscription + international formatting
283
+ end
284
+ ```
285
+
286
+ ### Persona with Mode Override
287
+
288
+ ```ruby
289
+ # Persona as base, mode overrides specifics
290
+ FakeDataDSL.as(:premium_customer).mode(:edge) do
291
+ user = FakeDataDSL.generate("User")
292
+ # Premium overrides + edge case values for other fields
293
+ end
294
+ ```
295
+
296
+ ### Persona with Additional Overrides
297
+
298
+ ```ruby
299
+ FakeDataDSL.as(:happy_path).override(active: false) do
300
+ user = FakeDataDSL.generate("User")
301
+ # Happy path + explicitly inactive
302
+ end
303
+ ```
304
+
305
+ ## Testing Patterns
306
+
307
+ ### Test All Personas
308
+
309
+ ```ruby
310
+ RSpec.describe "API Endpoint" do
311
+ FakeDataDSL::Personas.all.each do |persona|
312
+ context "with #{persona.name} persona" do
313
+ let(:data) { FakeDataDSL.as(persona.name) { generate("Request") } }
314
+
315
+ it "responds successfully" do
316
+ post "/api/endpoint", params: data
317
+ expect(response).to have_http_status(:ok)
318
+ end
319
+ end
320
+ end
321
+ end
322
+ ```
323
+
324
+ ### Persona Matrix
325
+
326
+ ```ruby
327
+ RSpec.describe "Security" do
328
+ # Test dangerous personas don't cause issues
329
+ [:hacker, :problematic, :edge_case].each do |persona|
330
+ context "with #{persona} data" do
331
+ let(:input) { FakeDataDSL.as(persona) { generate("UserInput") } }
332
+
333
+ it "sanitizes input" do
334
+ result = Sanitizer.clean(input)
335
+ expect(result).not_to include("DROP TABLE")
336
+ expect(result).not_to include("<script>")
337
+ end
338
+ end
339
+ end
340
+ end
341
+ ```
342
+
343
+ ### Persona-Specific Assertions
344
+
345
+ ```ruby
346
+ RSpec.describe "Order Processing" do
347
+ context "as premium customer" do
348
+ include_persona :premium_customer
349
+
350
+ it "applies premium discount" do
351
+ order = FakeDataDSL.generate("Order")
352
+ processed = OrderProcessor.process(order, user)
353
+ expect(processed.discount_rate).to eq(0.15)
354
+ end
355
+ end
356
+
357
+ context "as free user" do
358
+ include_persona :free_user
359
+
360
+ it "applies no discount" do
361
+ order = FakeDataDSL.generate("Order")
362
+ processed = OrderProcessor.process(order, user)
363
+ expect(processed.discount_rate).to eq(0)
364
+ end
365
+ end
366
+ end
367
+ ```
368
+
369
+ ## API Reference
370
+
371
+ ### Personas.define
372
+
373
+ ```ruby
374
+ FakeDataDSL::Personas.define(name, options = {}, &block)
375
+ ```
376
+
377
+ **Parameters:**
378
+ - `name` - Symbol name for the persona
379
+ - `options[:extends]` - Parent persona(s) to inherit from
380
+ - `block` - Persona definition block
381
+
382
+ ### Persona DSL Methods
383
+
384
+ Inside a persona definition block:
385
+
386
+ ```ruby
387
+ FakeDataDSL::Personas.define(:example) do
388
+ # Set generation mode
389
+ mode :random # :random, :edge, :invalid, :hostile, :mixed
390
+
391
+ # Set locale for Faker
392
+ locale :en # or [:en, :de, :ja] for mixed
393
+
394
+ # Set default seed
395
+ seed 42
396
+
397
+ # Add field overrides for a schema
398
+ override "SchemaName", field: value, other_field: other_value
399
+
400
+ # Add behaviors
401
+ behavior :latency, min: 100, max: 500
402
+ behavior :failure, probability: 0.05
403
+
404
+ # Add description
405
+ description "A persona representing premium customers"
406
+ end
407
+ ```
408
+
409
+ ### FakeDataDSL.as
410
+
411
+ ```ruby
412
+ FakeDataDSL.as(persona_name, **options, &block)
413
+ ```
414
+
415
+ **Parameters:**
416
+ - `persona_name` - Symbol name of the persona
417
+ - `options` - Override persona parameters
418
+ - `block` - Block to execute with persona active
419
+
420
+ **Returns:** Result of the block
421
+
422
+ ### Personas.all
423
+
424
+ ```ruby
425
+ FakeDataDSL::Personas.all
426
+ # => Array of all defined personas
427
+ ```
428
+
429
+ ### Personas.find
430
+
431
+ ```ruby
432
+ FakeDataDSL::Personas.find(:happy_path)
433
+ # => Persona instance
434
+ ```
435
+
436
+ ## Best Practices
437
+
438
+ ### 1. Name Personas by User Type
439
+
440
+ ```ruby
441
+ # Good: Descriptive user archetypes
442
+ :premium_customer
443
+ :trial_user
444
+ :enterprise_admin
445
+ :churned_customer
446
+
447
+ # Avoid: Technical descriptions
448
+ :random_data
449
+ :edge_mode_user
450
+ :test_data_1
451
+ ```
452
+
453
+ ### 2. Document Persona Purpose
454
+
455
+ ```ruby
456
+ FakeDataDSL::Personas.define(:fraud_suspect) do
457
+ description <<~DESC
458
+ A user account showing suspicious activity patterns:
459
+ - Multiple failed payment attempts
460
+ - Mismatched billing/shipping addresses
461
+ - Recently created account with high-value orders
462
+ DESC
463
+
464
+ override "User",
465
+ created_at: 1.day.ago,
466
+ failed_payments: 3,
467
+ billing_country: "US",
468
+ shipping_country: "NG"
469
+ end
470
+ ```
471
+
472
+ ### 3. Keep Personas Focused
473
+
474
+ ```ruby
475
+ # Good: Single responsibility
476
+ FakeDataDSL::Personas.define(:international_user) do
477
+ locale [:zh, :ar, :ru]
478
+ end
479
+
480
+ FakeDataDSL::Personas.define(:premium_user) do
481
+ override "User", subscription: "premium"
482
+ end
483
+
484
+ # Use combinations
485
+ FakeDataDSL.as(:international_user, :premium_user) { ... }
486
+ ```
487
+
488
+ ### 4. Test Coverage with Personas
489
+
490
+ ```ruby
491
+ # Ensure critical paths are tested with multiple personas
492
+ CRITICAL_PERSONAS = [:happy_path, :edge_case, :hacker, :international]
493
+
494
+ RSpec.describe "Payment Processing" do
495
+ CRITICAL_PERSONAS.each do |persona|
496
+ it "handles #{persona} correctly" do
497
+ # Test each persona
498
+ end
499
+ end
500
+ end
501
+ ```
502
+
503
+ ## Troubleshooting
504
+
505
+ ### Persona Not Found
506
+
507
+ ```ruby
508
+ # Error: Unknown persona: :my_persona
509
+
510
+ # Fix: Define before use
511
+ FakeDataDSL::Personas.define(:my_persona) { ... }
512
+
513
+ # Or check available personas
514
+ FakeDataDSL::Personas.all.map(&:name)
515
+ # => [:happy_path, :edge_case, ...]
516
+ ```
517
+
518
+ ### Overrides Not Applied
519
+
520
+ ```ruby
521
+ # Make sure override schema name matches exactly
522
+ FakeDataDSL::Personas.define(:test) do
523
+ override "User", active: true # ✓ Matches "User" schema
524
+ override "user", active: true # ✗ Case sensitive!
525
+ override :User, active: true # ✗ Symbol won't match string
526
+ end
527
+ ```
528
+
529
+ ### Inheritance Conflicts
530
+
531
+ ```ruby
532
+ # Child overrides take precedence
533
+ FakeDataDSL::Personas.define(:parent) do
534
+ override "User", status: "active"
535
+ end
536
+
537
+ FakeDataDSL::Personas.define(:child, extends: :parent) do
538
+ override "User", status: "pending" # This wins
539
+ end
540
+ ```
541
+
542
+ ## See Also
543
+
544
+ - [Generation Modes](generation_modes.md)
545
+ - [Behaviors](behaviors.md)
546
+ - [Scenarios](SCENARIOS.md)
547
+ - [Factory Bot Integration](FACTORY_BOT.md)