glib-web 3.11.0 → 3.12.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.
- checksums.yaml +4 -4
- data/app/helpers/glib/enum_helper.rb +3 -2
- data/app/helpers/glib/forms_helper.rb +0 -0
- data/app/helpers/glib/json_ui/action_builder/components.rb +5 -0
- data/app/helpers/glib/json_ui/action_builder/popovers.rb +1 -0
- data/app/helpers/glib/urls_helper.rb +2 -1
- data/app/models/concerns/glib/enum_humanization.rb +4 -3
- data/app/models/concerns/glib/soft_deletable.rb +18 -6
- data/app/views/json_ui/garage/actions/_reload.json.jbuilder +0 -0
- data/app/views/json_ui/garage/forms/basic_post.json.jbuilder +21 -4
- data/app/views/json_ui/garage/forms/dynamic_group.json.jbuilder +0 -0
- data/lib/glib/json_crawler/action_crawlers/forms_submit.rb +13 -6
- data/lib/glib/json_crawler/router.rb +11 -2
- data/lib/glib/test_helpers.rb +105 -15
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: df6b1ad5defcb6d77fa2cff5f8daef5615ca3ce0965efeb7263a8d42e9e9ebe6
|
4
|
+
data.tar.gz: 8bb3862f75b2d32c3284efc9de83afaa051c4e915a3ed5c1fe1b28b78e5fc0dd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: daa8778895e12cfb01ef928b27a61bc4b8cfbe20eb9c61a7e242a2ae63c8d8690cd45d348335832f79ff2cc3906b7f4c6c4bdfcc415f9db0ee297beb1ee29b6d
|
7
|
+
data.tar.gz: c002c3203aedaff266113d6dc1ba50320010df33d53f82489cbe21fc207eb2069dc1fa82ed8934dfeccb2bc7c6c611788fbc3dadaa21769ff59039a984df90b4
|
@@ -7,8 +7,9 @@ module Glib
|
|
7
7
|
text = clazz.glib_enum_humanize(enum_field, i)
|
8
8
|
if include_hints
|
9
9
|
i18n_key = clazz.model_name.i18n_key
|
10
|
-
hint = I18n.t("dt_models.#{i18n_key}.#{enum_name.pluralize}.#{i}.hint")
|
11
|
-
|
10
|
+
if (hint = I18n.t("dt_models.#{i18n_key}.#{enum_name.pluralize}.#{i}.hint")).present?
|
11
|
+
text += " #{hint}"
|
12
|
+
end
|
12
13
|
end
|
13
14
|
{ text: text, value: i }
|
14
15
|
end
|
File without changes
|
@@ -19,11 +19,12 @@ module Glib
|
|
19
19
|
module ClassMethods
|
20
20
|
def glib_enum_humanize(enum_name, enum_value, default_translation = nil)
|
21
21
|
if enum_value
|
22
|
+
translation_key = "activerecord.attributes.#{model_name.i18n_key}.#{enum_name.to_s.pluralize}.#{enum_value}"
|
23
|
+
|
22
24
|
if default_translation.nil? && Rails.env.development?
|
23
|
-
|
24
|
-
I18n.t(i18n_key, raise: I18n::MissingTranslationData)
|
25
|
+
I18n.t(translation_key, raise: I18n::MissingTranslationData)
|
25
26
|
else
|
26
|
-
I18n.t(
|
27
|
+
I18n.t(translation_key, default: default_translation)
|
27
28
|
end
|
28
29
|
end
|
29
30
|
end
|
@@ -42,7 +42,7 @@ module Glib
|
|
42
42
|
|
43
43
|
hard_destroy
|
44
44
|
when :disallowed
|
45
|
-
raise_hard_delete_disallowed
|
45
|
+
raise_hard_delete_disallowed(4502)
|
46
46
|
else
|
47
47
|
raise "Unsupported on_mark_for_destruction behaviour: #{behaviour}"
|
48
48
|
end
|
@@ -50,7 +50,7 @@ module Glib
|
|
50
50
|
return true # Tell Rails that destroy has succeeded
|
51
51
|
end
|
52
52
|
|
53
|
-
raise_hard_delete_disallowed
|
53
|
+
raise_hard_delete_disallowed(4501)
|
54
54
|
end
|
55
55
|
|
56
56
|
|
@@ -79,7 +79,9 @@ module Glib
|
|
79
79
|
# records are updated/validated one at a time.
|
80
80
|
# Besides, it's probably not a good idea to prevent soft-deletion of objects that are already not valid.
|
81
81
|
def _soft_destroy
|
82
|
+
before_soft_destroy
|
82
83
|
update_columns(deleted_at: DateTime.current)
|
84
|
+
after_soft_destroy
|
83
85
|
soft_destroy_associated_records
|
84
86
|
end
|
85
87
|
|
@@ -99,8 +101,8 @@ module Glib
|
|
99
101
|
end
|
100
102
|
end
|
101
103
|
|
102
|
-
def raise_hard_delete_disallowed
|
103
|
-
raise ActiveRecord::ConfigurationError, "Hard deletion is not allowed for #{self.class.name}"
|
104
|
+
def raise_hard_delete_disallowed(code)
|
105
|
+
raise ActiveRecord::ConfigurationError, "Hard deletion is not allowed for #{self.class.name} (error #{code})"
|
104
106
|
end
|
105
107
|
|
106
108
|
def process_soft_deletable_relationship(relationship, &block)
|
@@ -110,8 +112,10 @@ module Glib
|
|
110
112
|
# to existing objects which could cause a side effect.
|
111
113
|
relation = send(relationship)
|
112
114
|
|
113
|
-
|
114
|
-
|
115
|
+
# Use `each` instead of `find_each` because `each` is cached which is important to retain the
|
116
|
+
# `marked_for_destruction` status.
|
117
|
+
if relation.respond_to?(:each)
|
118
|
+
relation.each do |record|
|
115
119
|
block.call(record)
|
116
120
|
end
|
117
121
|
else
|
@@ -140,6 +144,14 @@ module Glib
|
|
140
144
|
def soft_deletable_associations
|
141
145
|
[]
|
142
146
|
end
|
147
|
+
|
148
|
+
def before_soft_destroy
|
149
|
+
# To be overridden
|
150
|
+
end
|
151
|
+
|
152
|
+
def after_soft_destroy
|
153
|
+
# To be overridden
|
154
|
+
end
|
143
155
|
end
|
144
156
|
end
|
145
157
|
end
|
File without changes
|
@@ -1,14 +1,31 @@
|
|
1
1
|
name, _ = params.require(:user).values_at(:name)
|
2
|
+
is_valid = name.present?
|
2
3
|
json_ui_response json do |action|
|
3
|
-
if !
|
4
|
+
if !is_valid
|
4
5
|
action.dialogs_alert message: 'Please enter name'
|
5
6
|
else
|
6
7
|
if params[:mode] == 'dialog'
|
7
|
-
action
|
8
|
-
|
9
|
-
|
8
|
+
render "#{@path_prefix}/forms/alert_post_data", action: action
|
9
|
+
|
10
|
+
# action.dialogs_close onClose: ->(subaction) do
|
11
|
+
# render "#{@path_prefix}/forms/alert_post_data", action: subaction
|
12
|
+
# end
|
10
13
|
else
|
11
14
|
render "#{@path_prefix}/forms/alert_post_data", action: action
|
12
15
|
end
|
13
16
|
end
|
14
17
|
end
|
18
|
+
|
19
|
+
if params[:mode] == 'dialog' && is_valid
|
20
|
+
json.title 'This is a response'
|
21
|
+
|
22
|
+
# This should update the content of the dialog.
|
23
|
+
page = json_ui_page json
|
24
|
+
page.scroll \
|
25
|
+
width: 'matchParent',
|
26
|
+
padding: glib_json_padding_body,
|
27
|
+
childViews: ->(scroll) do
|
28
|
+
scroll.label text: 'Success!'
|
29
|
+
scroll.spacer height: 20
|
30
|
+
end
|
31
|
+
end
|
File without changes
|
@@ -56,24 +56,31 @@ module Glib
|
|
56
56
|
json = @http.patch url, action, params
|
57
57
|
perform(json['onResponse'])
|
58
58
|
when :post
|
59
|
-
if (
|
60
|
-
|
61
|
-
|
59
|
+
if (groups = form_post_param_groups)
|
60
|
+
groups.each do |group_params|
|
61
|
+
json = @http.post url, action, group_params
|
62
|
+
perform(json['onResponse'])
|
63
|
+
end
|
62
64
|
else
|
63
65
|
@http.router.log action, url
|
64
66
|
end
|
65
67
|
end
|
66
68
|
end
|
67
69
|
|
68
|
-
def
|
70
|
+
def form_post_param_groups
|
69
71
|
route = Rails.application.routes.recognize_path(@http.router.page_url)
|
70
72
|
action_path = "#{route[:controller]}##{route[:action]}"
|
71
73
|
|
72
|
-
|
74
|
+
post_request_scenarios[action_path]
|
73
75
|
end
|
74
76
|
|
77
|
+
# # Redeclare this class and implement this method.
|
78
|
+
# def post_data
|
79
|
+
# {}
|
80
|
+
# end
|
81
|
+
|
75
82
|
# Redeclare this class and implement this method.
|
76
|
-
def
|
83
|
+
def post_request_scenarios
|
77
84
|
{}
|
78
85
|
end
|
79
86
|
end
|
@@ -91,9 +91,18 @@ module Glib
|
|
91
91
|
end
|
92
92
|
end
|
93
93
|
|
94
|
-
def follow(http,
|
94
|
+
def follow(http, target_routers)
|
95
|
+
if !target_routers.is_a?(Array)
|
96
|
+
target_routers = [target_routers]
|
97
|
+
end
|
98
|
+
|
99
|
+
target_actions = Set.new
|
100
|
+
target_routers.each do |router|
|
101
|
+
target_actions += router.read_only_actions
|
102
|
+
end
|
103
|
+
|
95
104
|
@depth += 1
|
96
|
-
|
105
|
+
target_actions.each do |crawler_action|
|
97
106
|
action, url = crawler_action
|
98
107
|
http.get(url, action, {}, false)
|
99
108
|
end
|
data/lib/glib/test_helpers.rb
CHANGED
@@ -1,35 +1,125 @@
|
|
1
1
|
module Glib
|
2
2
|
module TestHelpers
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
included do
|
6
|
+
extend ClassMethods
|
7
|
+
end
|
8
|
+
|
9
|
+
module ClassMethods
|
10
|
+
def define_crawler_test(user, crawled_at, &on_after_crawl)
|
11
|
+
test "crawl api for #{user[:email]} #{user[:device]} #{user[:version] || 'current'}" do
|
12
|
+
Timecop.freeze(crawled_at || user[:crawled_at]) do
|
13
|
+
router = crawl_json_pages(user)
|
14
|
+
on_after_crawl&.call(router)
|
15
|
+
end
|
16
|
+
|
17
|
+
# Right now we're not benefitting from these due to Ruby's limited concurrency.
|
18
|
+
# Thread.new(user) { crawl_pages(user) }.join
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
HOST = 'www.lvh.me:3000'
|
24
|
+
# LOG_DIR = File.expand_path(
|
25
|
+
# File.join(File.dirname(__FILE__), 'integration/json_ui_crawler_test_results')
|
26
|
+
# )
|
27
|
+
|
3
28
|
def response_assert_equal
|
4
29
|
expected = __get_previous_result_from_git
|
5
|
-
result =
|
6
|
-
assert_equal JSON.parse(expected), JSON.parse(result), "Result mismatch! #{__git_is_available? ? `git diff #{
|
30
|
+
result = __log_controller_data(response.body)
|
31
|
+
assert_equal JSON.parse(expected), JSON.parse(result), "Result mismatch! #{__git_is_available? ? `git diff #{__controller_log_dir}/#{__controller_log_file}` : ''}"
|
32
|
+
end
|
33
|
+
|
34
|
+
def crawl_json_pages(user, check_result: true, log_file: nil, &block)
|
35
|
+
__execute_crawler(user, check_result: true) do |router, http|
|
36
|
+
path = user[:path] ? "#{user[:path]}?format=json" : '/users/me?format=json&redirect=default'
|
37
|
+
router.host = HOST
|
38
|
+
router.step(
|
39
|
+
http,
|
40
|
+
'onClick' => {
|
41
|
+
'action' => user[:action] || 'initiate_navigation',
|
42
|
+
'url' => user[:url] || "http://#{HOST}#{path}"
|
43
|
+
}
|
44
|
+
)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def retrace_json_pages(user, guiding_routers:)
|
49
|
+
__execute_crawler(user, check_result: true) do |router, http|
|
50
|
+
router.follow(http, guiding_routers)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def logout
|
55
|
+
delete logout_url
|
56
|
+
assert_response :success
|
57
|
+
end
|
58
|
+
|
59
|
+
def logout_url
|
60
|
+
"http://#{HOST}/users/sign_out.json"
|
7
61
|
end
|
8
62
|
|
9
63
|
private
|
64
|
+
def __execute_crawler(user, check_result: true, log_file: nil, &block)
|
65
|
+
auth_token = login user
|
66
|
+
user[:token] = auth_token
|
67
|
+
|
68
|
+
router = Glib::JsonCrawler::Router.new
|
69
|
+
http = Glib::JsonCrawler::Http.new(self, user, router)
|
70
|
+
block.call(router, http)
|
71
|
+
|
72
|
+
logout
|
73
|
+
|
74
|
+
if check_result
|
75
|
+
log_file = "#{user[:email]}[#{user[:device]}][#{user[:version] || 'current'}].txt" if log_file.nil?
|
76
|
+
|
77
|
+
file_path = File.join(__crawler_log_dir, log_file)
|
78
|
+
expected = File.exist?(file_path) ? File.read(file_path) : ''
|
79
|
+
result = router.logger
|
80
|
+
File.write(file_path, result)
|
81
|
+
assert_equal expected, result, "Result mismatch! #{log_file.sub(/\.txt$/, '')}"
|
82
|
+
end
|
83
|
+
|
84
|
+
router
|
85
|
+
end
|
86
|
+
|
10
87
|
def __git_is_available?
|
11
88
|
@__git_is_available ||= (`git status 2>&1` =~ /fatal/).nil?
|
12
89
|
end
|
13
90
|
|
14
|
-
def
|
15
|
-
if @
|
16
|
-
@
|
91
|
+
def __crawler_log_dir
|
92
|
+
if @__crawler_log_dir.nil?
|
93
|
+
@__crawler_log_dir = File.expand_path(
|
94
|
+
"#{Rails.root}/test/integration/#{self.class.to_s.underscore}_results",
|
95
|
+
File.dirname(__FILE__)
|
96
|
+
)
|
97
|
+
unless File.directory?(@__crawler_log_dir)
|
98
|
+
FileUtils.mkdir_p(@__crawler_log_dir)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
@__crawler_log_dir
|
102
|
+
end
|
103
|
+
|
104
|
+
def __controller_log_dir
|
105
|
+
if @__controller_log_dir.nil?
|
106
|
+
@__controller_log_dir = File.expand_path(
|
17
107
|
"#{Rails.root}/test/controllers/#{self.class.to_s.underscore}_results",
|
18
108
|
File.dirname(__FILE__)
|
19
109
|
)
|
20
|
-
unless File.directory?(@
|
21
|
-
FileUtils.mkdir_p(@
|
110
|
+
unless File.directory?(@__controller_log_dir)
|
111
|
+
FileUtils.mkdir_p(@__controller_log_dir)
|
22
112
|
end
|
23
113
|
end
|
24
|
-
@
|
114
|
+
@__controller_log_dir
|
25
115
|
end
|
26
116
|
|
27
|
-
def
|
28
|
-
@
|
117
|
+
def __controller_log_file
|
118
|
+
@__controller_log_file ||= "#{self.method_name}.json"
|
29
119
|
end
|
30
120
|
|
31
|
-
def
|
32
|
-
file = File.open("#{File.join(
|
121
|
+
def __log_controller_data(json)
|
122
|
+
file = File.open("#{File.join(__controller_log_dir, __controller_log_file)}", 'w') do |f|
|
33
123
|
f << JSON.pretty_generate(JSON.parse(json))
|
34
124
|
end
|
35
125
|
file.close
|
@@ -38,12 +128,12 @@ module Glib
|
|
38
128
|
|
39
129
|
def __get_previous_result_from_git
|
40
130
|
if __git_is_available?
|
41
|
-
`git checkout -- "#{File.join(
|
131
|
+
`git checkout -- "#{File.join(__controller_log_dir, __controller_log_file)}" > /dev/null 2>&1`
|
42
132
|
end
|
43
133
|
if File.exist?(
|
44
|
-
File.join(
|
134
|
+
File.join(__controller_log_dir, __controller_log_file)
|
45
135
|
)
|
46
|
-
File.read(File.join(
|
136
|
+
File.read(File.join(__controller_log_dir, __controller_log_file))
|
47
137
|
else
|
48
138
|
"\{\}"
|
49
139
|
end
|