crspec 0.1.0 → 0.1.1
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.
- checksums.yaml +4 -4
- data/README.md +67 -17
- data/benchmark/README.md +56 -0
- data/benchmark/run.rb +72 -0
- data/benchmark/spec/user_service_crspec_spec.rb +15 -0
- data/benchmark/spec/user_service_rspec_spec.rb +16 -0
- data/benchmark/target_service.rb +12 -0
- data/benchmark/test/user_service_test.rb +18 -0
- data/demo.rb +6 -3
- data/lib/crspec/cli.rb +34 -3
- data/lib/crspec/configuration.rb +59 -0
- data/lib/crspec/example_group.rb +31 -0
- data/lib/crspec/execution_context.rb +1 -1
- data/lib/crspec/generators/init.rb +94 -0
- data/lib/crspec/matchers.rb +55 -0
- data/lib/crspec/mock/double.rb +8 -1
- data/lib/crspec/rails/database_isolation.rb +6 -15
- data/lib/crspec/rails/parallel.rb +1 -1
- data/lib/crspec/rails/request_helpers.rb +96 -0
- data/lib/crspec/transpiler/cli.rb +6 -6
- data/lib/crspec/version.rb +1 -1
- data/lib/crspec.rb +3 -0
- data/samples/book_store/.dockerignore +51 -0
- data/samples/book_store/.gitattributes +9 -0
- data/samples/book_store/.github/dependabot.yml +12 -0
- data/samples/book_store/.github/workflows/ci.yml +130 -0
- data/samples/book_store/.gitignore +35 -0
- data/samples/book_store/.kamal/hooks/docker-setup.sample +3 -0
- data/samples/book_store/.kamal/hooks/post-app-boot.sample +3 -0
- data/samples/book_store/.kamal/hooks/post-deploy.sample +14 -0
- data/samples/book_store/.kamal/hooks/post-proxy-reboot.sample +3 -0
- data/samples/book_store/.kamal/hooks/pre-app-boot.sample +3 -0
- data/samples/book_store/.kamal/hooks/pre-build.sample +51 -0
- data/samples/book_store/.kamal/hooks/pre-connect.sample +47 -0
- data/samples/book_store/.kamal/hooks/pre-deploy.sample +122 -0
- data/samples/book_store/.kamal/hooks/pre-proxy-reboot.sample +3 -0
- data/samples/book_store/.kamal/secrets +20 -0
- data/samples/book_store/.rubocop.yml +8 -0
- data/samples/book_store/.ruby-version +1 -0
- data/samples/book_store/Dockerfile +77 -0
- data/samples/book_store/Gemfile +67 -0
- data/samples/book_store/Gemfile.lock +572 -0
- data/samples/book_store/README.md +24 -0
- data/samples/book_store/Rakefile +6 -0
- data/samples/book_store/app/assets/images/.keep +0 -0
- data/samples/book_store/app/assets/stylesheets/application.css +10 -0
- data/samples/book_store/app/controllers/application_controller.rb +2 -0
- data/samples/book_store/app/controllers/books_controller.rb +30 -0
- data/samples/book_store/app/controllers/comments_controller.rb +21 -0
- data/samples/book_store/app/controllers/concerns/.keep +0 -0
- data/samples/book_store/app/controllers/users_controller.rb +21 -0
- data/samples/book_store/app/helpers/application_helper.rb +2 -0
- data/samples/book_store/app/helpers/books_helper.rb +2 -0
- data/samples/book_store/app/helpers/comments_helper.rb +2 -0
- data/samples/book_store/app/helpers/users_helper.rb +2 -0
- data/samples/book_store/app/javascript/application.js +3 -0
- data/samples/book_store/app/javascript/controllers/application.js +9 -0
- data/samples/book_store/app/javascript/controllers/hello_controller.js +7 -0
- data/samples/book_store/app/javascript/controllers/index.js +4 -0
- data/samples/book_store/app/jobs/application_job.rb +7 -0
- data/samples/book_store/app/mailers/application_mailer.rb +4 -0
- data/samples/book_store/app/models/application_record.rb +3 -0
- data/samples/book_store/app/models/book.rb +10 -0
- data/samples/book_store/app/models/comment.rb +6 -0
- data/samples/book_store/app/models/concerns/.keep +0 -0
- data/samples/book_store/app/models/user.rb +4 -0
- data/samples/book_store/app/views/layouts/application.html.erb +29 -0
- data/samples/book_store/app/views/layouts/mailer.html.erb +13 -0
- data/samples/book_store/app/views/layouts/mailer.text.erb +1 -0
- data/samples/book_store/app/views/pwa/manifest.json.erb +22 -0
- data/samples/book_store/app/views/pwa/service-worker.js +26 -0
- data/samples/book_store/bin/brakeman +7 -0
- data/samples/book_store/bin/bundler-audit +6 -0
- data/samples/book_store/bin/ci +6 -0
- data/samples/book_store/bin/dev +2 -0
- data/samples/book_store/bin/docker-entrypoint +8 -0
- data/samples/book_store/bin/importmap +4 -0
- data/samples/book_store/bin/jobs +6 -0
- data/samples/book_store/bin/kamal +16 -0
- data/samples/book_store/bin/rails +4 -0
- data/samples/book_store/bin/rake +4 -0
- data/samples/book_store/bin/rubocop +8 -0
- data/samples/book_store/bin/setup +35 -0
- data/samples/book_store/bin/thrust +5 -0
- data/samples/book_store/config/application.rb +27 -0
- data/samples/book_store/config/boot.rb +4 -0
- data/samples/book_store/config/bundler-audit.yml +5 -0
- data/samples/book_store/config/cable.yml +17 -0
- data/samples/book_store/config/cache.yml +16 -0
- data/samples/book_store/config/ci.rb +24 -0
- data/samples/book_store/config/credentials.yml.enc +1 -0
- data/samples/book_store/config/database.yml +45 -0
- data/samples/book_store/config/deploy.yml +119 -0
- data/samples/book_store/config/environment.rb +5 -0
- data/samples/book_store/config/environments/development.rb +78 -0
- data/samples/book_store/config/environments/production.rb +90 -0
- data/samples/book_store/config/environments/test.rb +53 -0
- data/samples/book_store/config/importmap.rb +7 -0
- data/samples/book_store/config/initializers/assets.rb +7 -0
- data/samples/book_store/config/initializers/content_security_policy.rb +29 -0
- data/samples/book_store/config/initializers/filter_parameter_logging.rb +8 -0
- data/samples/book_store/config/initializers/inflections.rb +16 -0
- data/samples/book_store/config/locales/en.yml +31 -0
- data/samples/book_store/config/puma.rb +42 -0
- data/samples/book_store/config/queue.yml +18 -0
- data/samples/book_store/config/recurring.yml +15 -0
- data/samples/book_store/config/routes.rb +17 -0
- data/samples/book_store/config/storage.yml +27 -0
- data/samples/book_store/config.ru +6 -0
- data/samples/book_store/db/cable_schema.rb +11 -0
- data/samples/book_store/db/cache_schema.rb +12 -0
- data/samples/book_store/db/migrate/20260731035441_create_users.rb +10 -0
- data/samples/book_store/db/migrate/20260731035506_create_books.rb +11 -0
- data/samples/book_store/db/migrate/20260731035528_create_comments.rb +11 -0
- data/samples/book_store/db/queue_schema.rb +129 -0
- data/samples/book_store/db/schema.rb +39 -0
- data/samples/book_store/db/seeds.rb +9 -0
- data/samples/book_store/lib/tasks/.keep +0 -0
- data/samples/book_store/log/.keep +0 -0
- data/samples/book_store/public/400.html +135 -0
- data/samples/book_store/public/404.html +135 -0
- data/samples/book_store/public/406-unsupported-browser.html +135 -0
- data/samples/book_store/public/422.html +135 -0
- data/samples/book_store/public/500.html +135 -0
- data/samples/book_store/public/icon.png +0 -0
- data/samples/book_store/public/icon.svg +3 -0
- data/samples/book_store/public/robots.txt +1 -0
- data/samples/book_store/script/.keep +0 -0
- data/samples/book_store/spec/models/book_spec.rb +42 -0
- data/samples/book_store/spec/models/comment_spec.rb +22 -0
- data/samples/book_store/spec/models/user_advanced_spec.rb +27 -0
- data/samples/book_store/spec/models/user_spec.rb +30 -0
- data/samples/book_store/spec/rails_helper.rb +36 -0
- data/samples/book_store/spec/rails_parallel_spec.rb +23 -0
- data/samples/book_store/spec/requests/books_spec.rb +21 -0
- data/samples/book_store/spec/requests/users_spec.rb +14 -0
- data/samples/book_store/spec/services/inventory_service_spec.rb +28 -0
- data/samples/book_store/spec/services/time_dependent_service_spec.rb +26 -0
- data/samples/book_store/spec/spec_helper.rb +16 -0
- data/samples/book_store/spec/system/book_store_system_spec.rb +18 -0
- data/samples/book_store/storage/.keep +0 -0
- data/samples/book_store/test/controllers/.keep +0 -0
- data/samples/book_store/test/controllers/books_controller_test.rb +7 -0
- data/samples/book_store/test/controllers/comments_controller_test.rb +7 -0
- data/samples/book_store/test/controllers/users_controller_test.rb +7 -0
- data/samples/book_store/test/fixtures/books.yml +11 -0
- data/samples/book_store/test/fixtures/comments.yml +11 -0
- data/samples/book_store/test/fixtures/files/.keep +0 -0
- data/samples/book_store/test/fixtures/users.yml +9 -0
- data/samples/book_store/test/helpers/.keep +0 -0
- data/samples/book_store/test/integration/.keep +0 -0
- data/samples/book_store/test/mailers/.keep +0 -0
- data/samples/book_store/test/models/.keep +0 -0
- data/samples/book_store/test/models/book_test.rb +7 -0
- data/samples/book_store/test/models/comment_test.rb +7 -0
- data/samples/book_store/test/models/user_test.rb +7 -0
- data/samples/book_store/test/test_helper.rb +15 -0
- data/samples/book_store/tmp/.keep +0 -0
- data/samples/book_store/tmp/pids/.keep +0 -0
- data/samples/book_store/tmp/storage/.keep +0 -0
- data/samples/book_store/vendor/.keep +0 -0
- data/samples/book_store/vendor/javascript/.keep +0 -0
- data/test/crspec/configuration_test.rb +76 -0
- metadata +152 -2
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
|
|
3
|
+
<html lang="en">
|
|
4
|
+
|
|
5
|
+
<head>
|
|
6
|
+
|
|
7
|
+
<title>We're sorry, but something went wrong (500 Internal Server Error)</title>
|
|
8
|
+
|
|
9
|
+
<meta charset="utf-8">
|
|
10
|
+
<meta name="viewport" content="initial-scale=1, width=device-width">
|
|
11
|
+
<meta name="robots" content="noindex, nofollow">
|
|
12
|
+
|
|
13
|
+
<style>
|
|
14
|
+
|
|
15
|
+
*, *::before, *::after {
|
|
16
|
+
box-sizing: border-box;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
* {
|
|
20
|
+
margin: 0;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
html {
|
|
24
|
+
font-size: 16px;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
body {
|
|
28
|
+
background: #FFF;
|
|
29
|
+
color: #261B23;
|
|
30
|
+
display: grid;
|
|
31
|
+
font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, Aptos, Roboto, "Segoe UI", "Helvetica Neue", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
|
|
32
|
+
font-size: clamp(1rem, 2.5vw, 2rem);
|
|
33
|
+
-webkit-font-smoothing: antialiased;
|
|
34
|
+
font-style: normal;
|
|
35
|
+
font-weight: 400;
|
|
36
|
+
letter-spacing: -0.0025em;
|
|
37
|
+
line-height: 1.4;
|
|
38
|
+
min-height: 100dvh;
|
|
39
|
+
place-items: center;
|
|
40
|
+
text-rendering: optimizeLegibility;
|
|
41
|
+
-webkit-text-size-adjust: 100%;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
#error-description {
|
|
45
|
+
fill: #d30001;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
#error-id {
|
|
49
|
+
fill: #f0eff0;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
@media (prefers-color-scheme: dark) {
|
|
53
|
+
body {
|
|
54
|
+
background: #101010;
|
|
55
|
+
color: #e0e0e0;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
#error-description {
|
|
59
|
+
fill: #FF6161;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
#error-id {
|
|
63
|
+
fill: #2c2c2c;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
a {
|
|
68
|
+
color: inherit;
|
|
69
|
+
font-weight: 700;
|
|
70
|
+
text-decoration: underline;
|
|
71
|
+
text-underline-offset: 0.0925em;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
b, strong {
|
|
75
|
+
font-weight: 700;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
i, em {
|
|
79
|
+
font-style: italic;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
main {
|
|
83
|
+
display: grid;
|
|
84
|
+
gap: 1em;
|
|
85
|
+
padding: 2em;
|
|
86
|
+
place-items: center;
|
|
87
|
+
text-align: center;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
main header {
|
|
91
|
+
width: min(100%, 12em);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
main header svg {
|
|
95
|
+
height: auto;
|
|
96
|
+
max-width: 100%;
|
|
97
|
+
width: 100%;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
main article {
|
|
101
|
+
width: min(100%, 30em);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
main article p {
|
|
105
|
+
font-size: 75%;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
main article br {
|
|
109
|
+
display: none;
|
|
110
|
+
|
|
111
|
+
@media(min-width: 48em) {
|
|
112
|
+
display: inline;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
</style>
|
|
117
|
+
|
|
118
|
+
</head>
|
|
119
|
+
|
|
120
|
+
<body>
|
|
121
|
+
|
|
122
|
+
<!-- This file lives in public/500.html -->
|
|
123
|
+
|
|
124
|
+
<main>
|
|
125
|
+
<header>
|
|
126
|
+
<svg height="172" viewBox="0 0 480 172" width="480" xmlns="http://www.w3.org/2000/svg"><path d="m101.23 93.8427c-8.1103 0-15.4098 3.7849-19.7354 8.3813h-36.2269v-99.21891h103.8143v37.03791h-68.3984v24.8722c5.1366-2.7035 15.1396-5.9477 24.6014-5.9477 35.146 0 56.233 22.7094 56.233 55.4215 0 34.605-23.791 57.315-60.558 57.315-37.8492 0-61.64-22.169-63.8028-55.963h42.9857c1.0814 10.814 9.1919 19.195 21.6281 19.195 11.355 0 19.465-8.381 19.465-20.547 0-11.625-7.299-20.5463-20.006-20.5463zm138.833 77.8613c-40.822 0-64.884-35.146-64.884-85.7015 0-50.5554 24.062-85.700907 64.884-85.700907 40.823 0 64.884 35.145507 64.884 85.700907 0 50.5555-24.061 85.7015-64.884 85.7015zm0-133.2831c-17.572 0-22.709 21.8984-22.709 47.5816 0 25.6835 5.137 47.5815 22.709 47.5815 17.303 0 22.71-21.898 22.71-47.5815 0-25.6832-5.407-47.5816-22.71-47.5816zm140.456 133.2831c-40.823 0-64.884-35.146-64.884-85.7015 0-50.5554 24.061-85.700907 64.884-85.700907 40.822 0 64.884 35.145507 64.884 85.700907 0 50.5555-24.062 85.7015-64.884 85.7015zm0-133.2831c-17.573 0-22.71 21.8984-22.71 47.5816 0 25.6835 5.137 47.5815 22.71 47.5815 17.302 0 22.709-21.898 22.709-47.5815 0-25.6832-5.407-47.5816-22.709-47.5816z" id="error-id"/><path d="m23.1377 68.9967v34.0033h-8.9162v-34.0033zm4.3157 34.0033v-24.921h8.6947v2.1598c1.3845-1.5506 3.8212-2.7136 6.701-2.7136 5.538 0 8.8054 3.5997 8.8054 9.1377v16.3371h-8.6393v-14.2327c0-2.049-1.0522-3.5443-3.2674-3.5443-1.7168 0-3.1567.9969-3.5997 2.7136v15.0634zm29.9913-8.5839v-9.5807h-3.655v-6.7564h3.655v-6.8671h8.5839v6.8671h5.2058v6.7564h-5.2058v8.307c0 1.9383.9415 2.769 2.6583 2.769.9414 0 1.9937-.2216 2.769-.5538v7.3654c-.9969.443-2.8798.775-4.8181.775-5.8703 0-9.1931-2.769-9.1931-9.0819zm32.3666-.1108h8.0301c-.8861 5.7597-5.2057 9.2487-11.6852 9.2487-7.6424 0-12.682-5.2613-12.682-13.0145 0-7.6978 5.3165-13.0143 12.5159-13.0143 7.6424 0 11.9621 5.095 11.9621 12.5159v2.1598h-16.1156c.2769 2.9905 1.8275 4.5965 4.3196 4.5965 1.7722 0 3.1567-.7753 3.6551-2.4921zm-3.8212-10.0237c-2.0491 0-3.4336 1.2737-3.9874 3.5997h7.5317c-.1107-2.0491-1.3845-3.5997-3.5443-3.5997zm31.4299-6.3134v8.3624c-1.052-.5538-2.215-.7753-3.599-.7753-2.382 0-3.988 1.0522-4.431 2.8244v14.6203h-8.694v-24.921h8.694v2.2152c1.219-1.6614 3.157-2.769 5.649-2.769 1.108 0 1.994.2215 2.381.443zm2.949 25.0318v-24.921h8.694v2.1598c1.385-1.5506 3.821-2.7136 6.701-2.7136 5.538 0 8.806 3.5997 8.806 9.1377v16.3371h-8.64v-14.2327c0-2.049-1.052-3.5443-3.267-3.5443-1.717 0-3.157.9969-3.6 2.7136v15.0634zm50.371 0h-8.363v-1.274c-.83.831-3.323 1.717-5.981 1.717-4.929 0-9.082-2.769-9.082-8.0301 0-4.818 4.153-7.9193 9.581-7.9193 2.049 0 4.485.6646 5.482 1.3845v-1.606c0-1.606-.941-2.9905-3.046-2.9905-1.606 0-2.547.7199-2.935 1.8275h-8.196c.72-4.8181 4.984-8.6393 11.408-8.6393 7.089 0 11.132 3.7659 11.132 10.2453zm-8.363-6.9779v-1.4399c-.554-1.0522-2.049-1.7167-3.655-1.7167-1.717 0-3.433.7199-3.433 2.3813 0 1.7168 1.716 2.4367 3.433 2.4367 1.606 0 3.101-.6645 3.655-1.6614zm20.742-29.0191v35.997h-8.694v-35.997zm13.036 25.9178h9.248c.72 2.326 2.714 3.489 5.483 3.489 2.713 0 4.596-1.163 4.596-3.2674 0-1.6061-1.052-2.326-3.212-2.8244l-6.534-1.3845c-4.985-1.1076-8.751-3.7105-8.751-9.47 0-6.6456 5.538-11.0206 13.07-11.0206 8.307 0 13.014 4.5411 13.956 10.4114h-8.695c-.72-1.8829-2.27-3.3228-5.205-3.3228-2.548 0-4.265 1.1076-4.265 2.9905 0 1.4953 1.052 2.326 2.825 2.7137l6.645 1.5506c5.815 1.3845 9.027 4.5412 9.027 9.8023 0 6.9778-5.87 10.9654-13.291 10.9654-8.141 0-13.679-3.9322-14.897-10.6332zm46.509 1.3845h8.031c-.887 5.7597-5.206 9.2487-11.686 9.2487-7.642 0-12.682-5.2613-12.682-13.0145 0-7.6978 5.317-13.0143 12.516-13.0143 7.643 0 11.962 5.095 11.962 12.5159v2.1598h-16.115c.277 2.9905 1.827 4.5965 4.319 4.5965 1.773 0 3.157-.7753 3.655-2.4921zm-3.821-10.0237c-2.049 0-3.433 1.2737-3.987 3.5997h7.532c-.111-2.0491-1.385-3.5997-3.545-3.5997zm31.431-6.3134v8.3624c-1.053-.5538-2.216-.7753-3.6-.7753-2.381 0-3.988 1.0522-4.431 2.8244v14.6203h-8.694v-24.921h8.694v2.2152c1.219-1.6614 3.157-2.769 5.649-2.769 1.108 0 1.994.2215 2.382.443zm18.288 25.0318h-7.809l-9.47-24.921h8.861l4.763 14.288 4.652-14.288h8.528zm25.614-8.6947h8.03c-.886 5.7597-5.206 9.2487-11.685 9.2487-7.642 0-12.682-5.2613-12.682-13.0145 0-7.6978 5.316-13.0143 12.516-13.0143 7.642 0 11.962 5.095 11.962 12.5159v2.1598h-16.116c.277 2.9905 1.828 4.5965 4.32 4.5965 1.772 0 3.157-.7753 3.655-2.4921zm-3.821-10.0237c-2.049 0-3.434 1.2737-3.988 3.5997h7.532c-.111-2.0491-1.384-3.5997-3.544-3.5997zm31.43-6.3134v8.3624c-1.052-.5538-2.215-.7753-3.6-.7753-2.381 0-3.987 1.0522-4.43 2.8244v14.6203h-8.695v-24.921h8.695v2.2152c1.218-1.6614 3.157-2.769 5.649-2.769 1.107 0 1.993.2215 2.381.443zm13.703-8.9715h24.312v7.6424h-15.562v5.3165h14.232v7.4763h-14.232v5.8703h15.562v7.6978h-24.312zm44.667 8.9715v8.3624c-1.052-.5538-2.215-.7753-3.6-.7753-2.381 0-3.987 1.0522-4.43 2.8244v14.6203h-8.695v-24.921h8.695v2.2152c1.218-1.6614 3.156-2.769 5.648-2.769 1.108 0 1.994.2215 2.382.443zm19.673 0v8.3624c-1.053-.5538-2.216-.7753-3.6-.7753-2.381 0-3.987 1.0522-4.43 2.8244v14.6203h-8.695v-24.921h8.695v2.2152c1.218-1.6614 3.156-2.769 5.648-2.769 1.108 0 1.994.2215 2.382.443zm26.769 12.5713c0 7.6978-5.15 13.0145-12.737 13.0145-7.532 0-12.738-5.3167-12.738-13.0145s5.206-13.0143 12.738-13.0143c7.587 0 12.737 5.3165 12.737 13.0143zm-8.529 0c0-3.4336-1.495-5.8703-4.208-5.8703-2.659 0-4.154 2.4367-4.154 5.8703s1.495 5.8149 4.154 5.8149c2.713 0 4.208-2.3813 4.208-5.8149zm28.082-12.5713v8.3624c-1.052-.5538-2.215-.7753-3.6-.7753-2.381 0-3.987 1.0522-4.43 2.8244v14.6203h-8.695v-24.921h8.695v2.2152c1.218-1.6614 3.157-2.769 5.649-2.769 1.107 0 1.993.2215 2.381.443z" id="error-description"/></svg>
|
|
127
|
+
</header>
|
|
128
|
+
<article>
|
|
129
|
+
<p><strong>We're sorry, but something went wrong.</strong><br> If you're the application owner check the logs for more information.</p>
|
|
130
|
+
</article>
|
|
131
|
+
</main>
|
|
132
|
+
|
|
133
|
+
</body>
|
|
134
|
+
|
|
135
|
+
</html>
|
|
Binary file
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# See https://www.robotstxt.org/robotstxt.html for documentation on how to use the robots.txt file
|
|
File without changes
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "../rails_helper"
|
|
4
|
+
require "securerandom"
|
|
5
|
+
|
|
6
|
+
Crspec.describe Book, type: :model do
|
|
7
|
+
let(:valid_attributes) { { name: "The Pragmatic Programmer #{SecureRandom.hex(4)}", author: "Andy Hunt", description: "Your journey to mastery" } }
|
|
8
|
+
subject(:book) { Book.new(valid_attributes) }
|
|
9
|
+
|
|
10
|
+
it "is valid with valid attributes" do
|
|
11
|
+
expect(book.valid?).to be(true)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
it "returns a formatted summary" do
|
|
15
|
+
expect(book.summary).to include("by Andy Hunt")
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
it "changes book count when saved" do
|
|
19
|
+
unique_name = "Unique Book #{SecureRandom.hex(4)}"
|
|
20
|
+
expect {
|
|
21
|
+
Book.create!(name: unique_name, author: "Andy Hunt", description: "Mastery")
|
|
22
|
+
}.to change { Book.where(name: unique_name).count }.by(1)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
context "when name is missing" do
|
|
26
|
+
let(:valid_attributes) { { name: nil, author: "Andy Hunt" } }
|
|
27
|
+
|
|
28
|
+
it "is invalid" do
|
|
29
|
+
expect(book.valid?).to be(false)
|
|
30
|
+
expect(book.errors[:name]).to include("can't be blank")
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
context "when author is missing" do
|
|
35
|
+
let(:valid_attributes) { { name: "Design Patterns", author: nil } }
|
|
36
|
+
|
|
37
|
+
it "is invalid" do
|
|
38
|
+
expect(book.valid?).to be(false)
|
|
39
|
+
expect(book.errors[:author]).to include("can't be blank")
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "../rails_helper"
|
|
4
|
+
|
|
5
|
+
Crspec.describe Comment, type: :model do
|
|
6
|
+
let(:book) { Book.new(name: "Clean Code", author: "Robert C. Martin") }
|
|
7
|
+
let(:comment_attributes) { { book: book, title: "Great Read!", text: "Highly recommended for all developers." } }
|
|
8
|
+
subject(:comment) { Comment.new(comment_attributes) }
|
|
9
|
+
|
|
10
|
+
it "is valid with a title, text, and book association" do
|
|
11
|
+
expect(comment.valid?).to be(true)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
context "when title is missing" do
|
|
15
|
+
let(:comment_attributes) { { book: book, title: nil, text: "Some feedback" } }
|
|
16
|
+
|
|
17
|
+
it "is invalid without a title" do
|
|
18
|
+
expect(comment.valid?).to be(false)
|
|
19
|
+
expect(comment.errors[:title]).to include("can't be blank")
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "../rails_helper"
|
|
4
|
+
require "securerandom"
|
|
5
|
+
|
|
6
|
+
Crspec.describe "Advanced User Capabilities", type: :model do
|
|
7
|
+
let!(:eager_user) { User.create!(name: "Eager User", email: "eager_#{SecureRandom.hex(4)}@example.com") }
|
|
8
|
+
|
|
9
|
+
before do
|
|
10
|
+
execution_context[:request_id] = "REQ-99"
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
it "evaluates eager let! before example execution" do
|
|
14
|
+
expect(eager_user.name).to eq("Eager User")
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
it "accesses fiber-isolated execution context" do
|
|
18
|
+
expect(execution_context[:request_id]).to eq("REQ-99")
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
it "validates message expectations with once count" do
|
|
22
|
+
notifier = double("UserNotifier")
|
|
23
|
+
expect(notifier).to receive(:send_welcome).once
|
|
24
|
+
|
|
25
|
+
notifier.send_welcome
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "../rails_helper"
|
|
4
|
+
|
|
5
|
+
Crspec.describe User, type: :model do
|
|
6
|
+
let(:user_attributes) { { name: "Alice Smith", email: "alice@example.com" } }
|
|
7
|
+
subject(:user) { User.new(user_attributes) }
|
|
8
|
+
|
|
9
|
+
it "validates primary user attributes" do
|
|
10
|
+
expect(user.valid?).to be(true)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
context "when email is missing" do
|
|
14
|
+
let(:user_attributes) { { name: "Alice Smith", email: nil } }
|
|
15
|
+
|
|
16
|
+
it "flags validation error on email" do
|
|
17
|
+
expect(user.valid?).to be(false)
|
|
18
|
+
expect(user.errors[:email]).to include("can't be blank")
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
context "when name is missing" do
|
|
23
|
+
let(:user_attributes) { { name: nil, email: "alice@example.com" } }
|
|
24
|
+
|
|
25
|
+
it "flags validation error on name" do
|
|
26
|
+
expect(user.valid?).to be(false)
|
|
27
|
+
expect(user.errors[:name]).to include("can't be blank")
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "spec_helper"
|
|
4
|
+
ENV["RAILS_ENV"] ||= "test"
|
|
5
|
+
require File.expand_path("../config/environment", __dir__) if File.exist?(File.expand_path("../config/environment.rb", __dir__))
|
|
6
|
+
|
|
7
|
+
# Prevent database truncation if environment is production
|
|
8
|
+
abort("The Rails environment is running in production mode!") if defined?(Rails) && Rails.env.production?
|
|
9
|
+
|
|
10
|
+
require "crspec"
|
|
11
|
+
|
|
12
|
+
# Checks for pending migrations and applies them before tests are run.
|
|
13
|
+
begin
|
|
14
|
+
ActiveRecord::Migration.maintain_test_schema! if defined?(ActiveRecord::Migration)
|
|
15
|
+
rescue ActiveRecord::PendingMigrationError => e
|
|
16
|
+
abort e.to_s
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# Including support files for tests
|
|
20
|
+
if defined?(Rails) && Rails.respond_to?(:root) && Rails.root
|
|
21
|
+
Rails.root.glob("spec/support/**/*.rb").each { |f| require f }
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
Crspec.configure do |config|
|
|
25
|
+
config.use_transactional_fixtures = true
|
|
26
|
+
config.infer_spec_type_from_file_location!
|
|
27
|
+
config.include(Crspec::Rails::RequestHelpers)
|
|
28
|
+
|
|
29
|
+
config.around(:each) do |example|
|
|
30
|
+
if defined?(ActiveRecord::Base) && config.use_transactional_fixtures
|
|
31
|
+
Crspec::Rails::DatabaseIsolation.wrap_example(example)
|
|
32
|
+
else
|
|
33
|
+
example.execute!
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "rails_helper"
|
|
4
|
+
|
|
5
|
+
Crspec.describe "Rails Parallel Worker Configuration" do
|
|
6
|
+
it "configures parallel worker environment variables and hooks" do
|
|
7
|
+
setup_called = false
|
|
8
|
+
teardown_called = false
|
|
9
|
+
|
|
10
|
+
Crspec::Rails::Parallel.parallelize(workers: 2) do
|
|
11
|
+
parallelize_setup { |_w| setup_called = true }
|
|
12
|
+
parallelize_teardown { |_w| teardown_called = true }
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
expect(Crspec::Rails::Parallel.worker_count).to eq(2)
|
|
16
|
+
|
|
17
|
+
Crspec::Rails::Parallel.setup_worker(1)
|
|
18
|
+
Crspec::Rails::Parallel.teardown_worker(1)
|
|
19
|
+
|
|
20
|
+
expect(setup_called).to be(true)
|
|
21
|
+
expect(teardown_called).to be(true)
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "../rails_helper"
|
|
4
|
+
|
|
5
|
+
Crspec.describe "Books API", type: :request do
|
|
6
|
+
it "lists books via GET" do
|
|
7
|
+
Book.create!(name: "Design Patterns", author: "Gang of Four", description: "Reusable Object-Oriented Software")
|
|
8
|
+
|
|
9
|
+
get "/books"
|
|
10
|
+
|
|
11
|
+
expect(response.status).to eq(200)
|
|
12
|
+
expect(json_response).not_to be_nil
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
it "creates a new book via POST" do
|
|
16
|
+
post "/books", params: { name: "Refactoring", author: "Martin Fowler", description: "Improving the Design of Existing Code" }
|
|
17
|
+
|
|
18
|
+
expect([ 200, 201 ]).to include(response.status)
|
|
19
|
+
expect(json_response[:name]).to eq("Refactoring")
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "../rails_helper"
|
|
4
|
+
require "securerandom"
|
|
5
|
+
|
|
6
|
+
Crspec.describe "Users API", type: :request do
|
|
7
|
+
it "creates a user via POST" do
|
|
8
|
+
email = "bob_#{SecureRandom.hex(4)}@example.com"
|
|
9
|
+
post "/users", params: { name: "Bob Martin", email: email }
|
|
10
|
+
|
|
11
|
+
expect([ 200, 201 ]).to include(response.status)
|
|
12
|
+
expect(json_response[:email]).to eq(email)
|
|
13
|
+
end
|
|
14
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "../spec_helper"
|
|
4
|
+
|
|
5
|
+
class InventoryService
|
|
6
|
+
def self.check_stock(book_id, client)
|
|
7
|
+
response = client.fetch_stock(book_id)
|
|
8
|
+
response[:in_stock] ? "In Stock (#{response[:quantity]} copies)" : "Out of Stock"
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
Crspec.describe InventoryService do
|
|
13
|
+
let(:client_double) { instance_double("StockClient") }
|
|
14
|
+
|
|
15
|
+
it "returns in-stock messaging using fiber-isolated doubles" do
|
|
16
|
+
allow(client_double).to receive(:fetch_stock).with(101).and_return(in_stock: true, quantity: 5)
|
|
17
|
+
|
|
18
|
+
result = InventoryService.check_stock(101, client_double)
|
|
19
|
+
expect(result).to eq("In Stock (5 copies)")
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
it "returns out-of-stock messaging" do
|
|
23
|
+
allow(client_double).to receive(:fetch_stock).with(202).and_return(in_stock: false, quantity: 0)
|
|
24
|
+
|
|
25
|
+
result = InventoryService.check_stock(202, client_double)
|
|
26
|
+
expect(result).to eq("Out of Stock")
|
|
27
|
+
end
|
|
28
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "../rails_helper"
|
|
4
|
+
require "active_support/testing/time_helpers"
|
|
5
|
+
|
|
6
|
+
class DiscountCalculator
|
|
7
|
+
def self.active_discount?
|
|
8
|
+
Time.now.month == 12
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
Crspec.describe DiscountCalculator do
|
|
13
|
+
include ActiveSupport::Testing::TimeHelpers
|
|
14
|
+
|
|
15
|
+
it "validates holiday discount in December" do
|
|
16
|
+
travel_to Time.zone.parse("2026-12-25 10:00:00") do
|
|
17
|
+
expect(DiscountCalculator.active_discount?).to be(true)
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
it "validates no holiday discount in July" do
|
|
22
|
+
travel_to Time.zone.parse("2026-07-15 10:00:00") do
|
|
23
|
+
expect(DiscountCalculator.active_discount?).to be(false)
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "crspec"
|
|
4
|
+
require "etc"
|
|
5
|
+
|
|
6
|
+
Crspec.configure do |config|
|
|
7
|
+
config.concurrency = Etc.nprocessors
|
|
8
|
+
|
|
9
|
+
config.before(:each) do
|
|
10
|
+
# Setup hooks executed before every spec example
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
config.after(:each) do
|
|
14
|
+
# Teardown hooks executed after every spec example
|
|
15
|
+
end
|
|
16
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "../rails_helper"
|
|
4
|
+
require "net/http"
|
|
5
|
+
|
|
6
|
+
Crspec.describe "BookStore System Server", type: :system do
|
|
7
|
+
it "boots Puma server and handles HTTP requests" do
|
|
8
|
+
app = ->(_env) { [ 200, { "Content-Type" => "text/html" }, [ "<h1>Welcome to BookStore</h1>" ] ] }
|
|
9
|
+
Crspec::Rails::SystemServer.start_concurrent_server!(app, 9889)
|
|
10
|
+
|
|
11
|
+
expect(Crspec::Rails::SystemServer.running?).to be(true)
|
|
12
|
+
|
|
13
|
+
uri = URI("http://127.0.0.1:9889/")
|
|
14
|
+
res = Net::HTTP.get_response(uri)
|
|
15
|
+
expect(res.code).to eq("200")
|
|
16
|
+
expect(res.body).to include("Welcome to BookStore")
|
|
17
|
+
end
|
|
18
|
+
end
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
ENV["RAILS_ENV"] ||= "test"
|
|
2
|
+
require_relative "../config/environment"
|
|
3
|
+
require "rails/test_help"
|
|
4
|
+
|
|
5
|
+
module ActiveSupport
|
|
6
|
+
class TestCase
|
|
7
|
+
# Run tests in parallel with specified workers
|
|
8
|
+
parallelize(workers: :number_of_processors)
|
|
9
|
+
|
|
10
|
+
# Setup all fixtures in test/fixtures/*.yml for all tests in alphabetical order.
|
|
11
|
+
fixtures :all
|
|
12
|
+
|
|
13
|
+
# Add more helper methods to be used by all tests here...
|
|
14
|
+
end
|
|
15
|
+
end
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|