skeleton-ui 0.1.1 → 0.1.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/html/index.html +4 -3
- data/html/java.html +43 -43
- data/html/ruby.html +43 -43
- data/lib/skeleton.rb +1 -1
- data/lib/skeleton/android.rb +14 -2
- data/lib/skeleton/ios.rb +14 -2
- data/lib/skeleton/languages.rb +25 -5
- data/lib/skeleton/root.rb +3 -3
- data/lib/skeleton/version.rb +1 -1
- 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: e5058006d22b824cf0ee9c8301301d727ba7154d1bb9ddedb8bcb0de8499dd2d
|
4
|
+
data.tar.gz: f90ceeb4bc70f85cb31985ea8624ef46b160f3c4ceaa23fcb7a264db61768c2b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ddda2e82e23fea5f6fd934c1067277993ade7f4d76fccf4acf1fbb86aec41c6e6d99a09751b971c9a56a34424f691f0b10b05c777bf0f84f0f2e19479c9d56ec
|
7
|
+
data.tar.gz: 30da30b97b76e1a9b4a652fb1803f983177d6a7faf87a5d53571bc0e611cabfd3122021b7adb6fd7284aeea4383ff64b97096c0bf25559f601262f6fa069d75f
|
data/html/index.html
CHANGED
@@ -16,9 +16,10 @@
|
|
16
16
|
<div class="row" style="min-height: 300px;">
|
17
17
|
<div class="col-md-8">
|
18
18
|
<h2>Get it:</h2>
|
19
|
-
<a href="ruby.html">Ruby</a>
|
20
|
-
<br>
|
21
|
-
<a href="
|
19
|
+
<a href="ruby.html">Ruby</a><br>
|
20
|
+
<a href="java.html">Java</a><br>
|
21
|
+
<a href="python.html">Python</a><br>
|
22
|
+
<a href="javascript.html">Javascript</a><br>
|
22
23
|
</div>
|
23
24
|
</div>
|
24
25
|
<footer class="my-5 pt-5 text-muted text-center text-small">
|
data/html/java.html
CHANGED
@@ -20,7 +20,7 @@
|
|
20
20
|
</div>
|
21
21
|
</div>
|
22
22
|
<div class="col-md-8">
|
23
|
-
<h4 class="mb-3">
|
23
|
+
<h4 class="mb-3">Page Objects:</h4>
|
24
24
|
<div class="content" id="content">
|
25
25
|
<pre><code>By myTargetDemo() {
|
26
26
|
return MobileBy.AccessibilityId("myTarget Demo");
|
@@ -73,54 +73,54 @@ By staticText11() {
|
|
73
73
|
</code></pre>
|
74
74
|
</div>
|
75
75
|
<br>
|
76
|
-
<h4 class="mb-3">
|
76
|
+
<h4 class="mb-3">Elements Tree:</h4>
|
77
77
|
<div class="content" id="content">
|
78
78
|
<pre><code>
|
79
|
-
t = 1.
|
80
|
-
t = 1.
|
81
|
-
Attributes: Application,
|
79
|
+
t = 1.43s Snapshot accessibility hierarchy for app with pid 74050
|
80
|
+
t = 1.45s Snapshot accessibility hierarchy for app with pid 74050
|
81
|
+
Attributes: Application, 0x60000019fbd0, pid: 74050, {{0.0, 0.0}, {414.0, 736.0}}, label: 'myTargetDemo'
|
82
82
|
Element subtree:
|
83
|
-
→Application,
|
84
|
-
Window,
|
85
|
-
Other,
|
86
|
-
NavigationBar,
|
87
|
-
Other,
|
88
|
-
Other,
|
89
|
-
Other,
|
90
|
-
Other,
|
91
|
-
Table,
|
92
|
-
Other,
|
93
|
-
Cell,
|
94
|
-
StaticText,
|
95
|
-
StaticText,
|
96
|
-
StaticText,
|
97
|
-
StaticText,
|
98
|
-
Cell,
|
99
|
-
StaticText,
|
100
|
-
StaticText,
|
101
|
-
StaticText,
|
102
|
-
StaticText,
|
103
|
-
Cell,
|
104
|
-
StaticText,
|
105
|
-
StaticText,
|
106
|
-
Other,
|
107
|
-
Window,
|
108
|
-
Other,
|
109
|
-
Other,
|
110
|
-
Window,
|
111
|
-
StatusBar,
|
112
|
-
Other,
|
113
|
-
Other,
|
114
|
-
Other,
|
115
|
-
Other,
|
116
|
-
Other,
|
117
|
-
Other,
|
83
|
+
→Application, 0x60000019fbd0, pid: 74050, {{0.0, 0.0}, {414.0, 736.0}}, label: 'myTargetDemo'
|
84
|
+
Window, 0x600000383b50, Main Window, {{0.0, 0.0}, {414.0, 736.0}}
|
85
|
+
Other, 0x60000019ff10, traits: 8589934592, {{0.0, 0.0}, {414.0, 736.0}}
|
86
|
+
NavigationBar, 0x600000380dd0, traits: 35192962023424, {{0.0, 20.0}, {414.0, 44.0}}, identifier: 'myTarget Demo'
|
87
|
+
Other, 0x600000380d00, traits: 8590000128, {{144.3, 31.7}, {125.7, 20.3}}, label: 'myTarget Demo'
|
88
|
+
Other, 0x600000380b60, traits: 8589934592, {{0.0, 0.0}, {414.0, 736.0}}
|
89
|
+
Other, 0x600000380a90, traits: 8589934592, {{0.0, 0.0}, {414.0, 736.0}}
|
90
|
+
Other, 0x6000003809c0, traits: 8589934592, {{0.0, 64.0}, {414.0, 672.0}}
|
91
|
+
Table, 0x6000003808f0, traits: 35192962023424, {{0.0, 64.0}, {414.0, 672.0}}
|
92
|
+
Other, 0x600000380000, traits: 8589934592, {{0.0, 64.0}, {414.0, 0.0}}
|
93
|
+
Cell, 0x600000380750, traits: 8589934592, {{0.0, 64.0}, {414.0, 280.0}}
|
94
|
+
StaticText, 0x6000003839b0, traits: 8589934656, {{16.0, 297.0}, {108.3, 32.3}}, label: '320x50 and 300x250 banners'
|
95
|
+
StaticText, 0x600000384510, traits: 8589934656, {{218.0, 297.0}, {119.3, 16.3}}, label: 'Fullscreen banners'
|
96
|
+
StaticText, 0x6000003845e0, traits: 8589934656, {{16.0, 270.0}, {72.3, 21.0}}, label: 'Banners'
|
97
|
+
StaticText, 0x600000382ff0, traits: 8589934656, {{218.0, 270.0}, {124.7, 21.0}}, label: 'Interstitial Ads'
|
98
|
+
Cell, 0x600000382f20, traits: 8589934592, {{0.0, 344.0}, {414.0, 280.0}}
|
99
|
+
StaticText, 0x600000382e50, traits: 8589934656, {{16.0, 577.0}, {134.0, 32.3}}, label: 'Advertisement inside app's content'
|
100
|
+
StaticText, 0x6000003846b0, traits: 8589934656, {{218.0, 577.0}, {118.3, 16.3}}, label: 'Instream video ads'
|
101
|
+
StaticText, 0x6000003830c0, traits: 8589934656, {{16.0, 550.0}, {92.7, 21.0}}, label: 'Native Ads'
|
102
|
+
StaticText, 0x600000384780, traits: 8589934656, {{218.0, 550.0}, {113.7, 21.0}}, label: 'Instream Ads'
|
103
|
+
Cell, 0x600000383400, traits: 8589934592, {{0.0, 624.0}, {414.0, 280.0}}
|
104
|
+
StaticText, 0x600000383330, traits: 8589934656, {{16.0, 857.0}, {134.7, 32.3}}, label: 'Insert your slotId and ad type'
|
105
|
+
StaticText, 0x600000383260, traits: 8589934656, {{16.0, 830.0}, {62.0, 21.0}}, label: 'Ad unit'
|
106
|
+
Other, 0x600000383190, traits: 8589934592, {{0.0, 904.0}, {414.0, 0.0}}
|
107
|
+
Window, 0x600000384850, {{0.0, 0.0}, {414.0, 736.0}}
|
108
|
+
Other, 0x600000384920, traits: 8589934592, {{0.0, 0.0}, {414.0, 736.0}}
|
109
|
+
Other, 0x6000003849f0, traits: 8589934592, {{0.0, 736.0}, {414.0, 226.0}}
|
110
|
+
Window, 0x600000384ac0, {{0.0, 0.0}, {414.0, 736.0}}
|
111
|
+
StatusBar, 0x600000384b90, {{0.0, 0.0}, {414.0, 20.0}}
|
112
|
+
Other, 0x600000384c60, {{0.0, 0.0}, {414.0, 20.0}}
|
113
|
+
Other, 0x600000384d30, {{0.0, 0.0}, {414.0, 20.0}}
|
114
|
+
Other, 0x600000384e00, traits: 8388608, {{6.0, 0.0}, {39.0, 20.0}}
|
115
|
+
Other, 0x600000384ed0, traits: 8388608, {{50.0, 0.0}, {14.0, 20.0}}, label: '3 of 3 Wi-Fi bars', value: SSID
|
116
|
+
Other, 0x600000384fa0, traits: 8389120, {{184.0, 0.0}, {50.0, 20.0}}, label: '5:04 PM'
|
117
|
+
Other, 0x600000385070, traits: 8388608, {{383.0, 0.0}, {26.0, 20.0}}, label: '-100% battery power'
|
118
118
|
Path to element:
|
119
|
-
→Application,
|
119
|
+
→Application, 0x60000019fbd0, pid: 74050, {{0.0, 0.0}, {414.0, 736.0}}, label: 'myTargetDemo'
|
120
120
|
Query chain:
|
121
|
-
→Find: Application "ru.mail.adman"
|
121
|
+
→Find: Application "ru.mail.adman" 0x6000000a3540
|
122
122
|
Output: {
|
123
|
-
Application,
|
123
|
+
Application, 0x60000019fbd0, pid: 74050, {{0.0, 0.0}, {414.0, 736.0}}, label: 'myTargetDemo'
|
124
124
|
}
|
125
125
|
|
126
126
|
|
data/html/ruby.html
CHANGED
@@ -20,7 +20,7 @@
|
|
20
20
|
</div>
|
21
21
|
</div>
|
22
22
|
<div class="col-md-8">
|
23
|
-
<h4 class="mb-3">
|
23
|
+
<h4 class="mb-3">Page Objects:</h4>
|
24
24
|
<div class="content" id="content">
|
25
25
|
<pre><code>def my_target_demo
|
26
26
|
return :accessibility_id, "myTarget Demo"
|
@@ -73,54 +73,54 @@ end
|
|
73
73
|
</code></pre>
|
74
74
|
</div>
|
75
75
|
<br>
|
76
|
-
<h4 class="mb-3">
|
76
|
+
<h4 class="mb-3">Elements Tree:</h4>
|
77
77
|
<div class="content" id="content">
|
78
78
|
<pre><code>
|
79
|
-
t = 1.
|
80
|
-
t = 1.
|
81
|
-
Attributes: Application,
|
79
|
+
t = 1.43s Snapshot accessibility hierarchy for app with pid 74050
|
80
|
+
t = 1.45s Snapshot accessibility hierarchy for app with pid 74050
|
81
|
+
Attributes: Application, 0x60000019fbd0, pid: 74050, {{0.0, 0.0}, {414.0, 736.0}}, label: 'myTargetDemo'
|
82
82
|
Element subtree:
|
83
|
-
→Application,
|
84
|
-
Window,
|
85
|
-
Other,
|
86
|
-
NavigationBar,
|
87
|
-
Other,
|
88
|
-
Other,
|
89
|
-
Other,
|
90
|
-
Other,
|
91
|
-
Table,
|
92
|
-
Other,
|
93
|
-
Cell,
|
94
|
-
StaticText,
|
95
|
-
StaticText,
|
96
|
-
StaticText,
|
97
|
-
StaticText,
|
98
|
-
Cell,
|
99
|
-
StaticText,
|
100
|
-
StaticText,
|
101
|
-
StaticText,
|
102
|
-
StaticText,
|
103
|
-
Cell,
|
104
|
-
StaticText,
|
105
|
-
StaticText,
|
106
|
-
Other,
|
107
|
-
Window,
|
108
|
-
Other,
|
109
|
-
Other,
|
110
|
-
Window,
|
111
|
-
StatusBar,
|
112
|
-
Other,
|
113
|
-
Other,
|
114
|
-
Other,
|
115
|
-
Other,
|
116
|
-
Other,
|
117
|
-
Other,
|
83
|
+
→Application, 0x60000019fbd0, pid: 74050, {{0.0, 0.0}, {414.0, 736.0}}, label: 'myTargetDemo'
|
84
|
+
Window, 0x600000383b50, Main Window, {{0.0, 0.0}, {414.0, 736.0}}
|
85
|
+
Other, 0x60000019ff10, traits: 8589934592, {{0.0, 0.0}, {414.0, 736.0}}
|
86
|
+
NavigationBar, 0x600000380dd0, traits: 35192962023424, {{0.0, 20.0}, {414.0, 44.0}}, identifier: 'myTarget Demo'
|
87
|
+
Other, 0x600000380d00, traits: 8590000128, {{144.3, 31.7}, {125.7, 20.3}}, label: 'myTarget Demo'
|
88
|
+
Other, 0x600000380b60, traits: 8589934592, {{0.0, 0.0}, {414.0, 736.0}}
|
89
|
+
Other, 0x600000380a90, traits: 8589934592, {{0.0, 0.0}, {414.0, 736.0}}
|
90
|
+
Other, 0x6000003809c0, traits: 8589934592, {{0.0, 64.0}, {414.0, 672.0}}
|
91
|
+
Table, 0x6000003808f0, traits: 35192962023424, {{0.0, 64.0}, {414.0, 672.0}}
|
92
|
+
Other, 0x600000380000, traits: 8589934592, {{0.0, 64.0}, {414.0, 0.0}}
|
93
|
+
Cell, 0x600000380750, traits: 8589934592, {{0.0, 64.0}, {414.0, 280.0}}
|
94
|
+
StaticText, 0x6000003839b0, traits: 8589934656, {{16.0, 297.0}, {108.3, 32.3}}, label: '320x50 and 300x250 banners'
|
95
|
+
StaticText, 0x600000384510, traits: 8589934656, {{218.0, 297.0}, {119.3, 16.3}}, label: 'Fullscreen banners'
|
96
|
+
StaticText, 0x6000003845e0, traits: 8589934656, {{16.0, 270.0}, {72.3, 21.0}}, label: 'Banners'
|
97
|
+
StaticText, 0x600000382ff0, traits: 8589934656, {{218.0, 270.0}, {124.7, 21.0}}, label: 'Interstitial Ads'
|
98
|
+
Cell, 0x600000382f20, traits: 8589934592, {{0.0, 344.0}, {414.0, 280.0}}
|
99
|
+
StaticText, 0x600000382e50, traits: 8589934656, {{16.0, 577.0}, {134.0, 32.3}}, label: 'Advertisement inside app's content'
|
100
|
+
StaticText, 0x6000003846b0, traits: 8589934656, {{218.0, 577.0}, {118.3, 16.3}}, label: 'Instream video ads'
|
101
|
+
StaticText, 0x6000003830c0, traits: 8589934656, {{16.0, 550.0}, {92.7, 21.0}}, label: 'Native Ads'
|
102
|
+
StaticText, 0x600000384780, traits: 8589934656, {{218.0, 550.0}, {113.7, 21.0}}, label: 'Instream Ads'
|
103
|
+
Cell, 0x600000383400, traits: 8589934592, {{0.0, 624.0}, {414.0, 280.0}}
|
104
|
+
StaticText, 0x600000383330, traits: 8589934656, {{16.0, 857.0}, {134.7, 32.3}}, label: 'Insert your slotId and ad type'
|
105
|
+
StaticText, 0x600000383260, traits: 8589934656, {{16.0, 830.0}, {62.0, 21.0}}, label: 'Ad unit'
|
106
|
+
Other, 0x600000383190, traits: 8589934592, {{0.0, 904.0}, {414.0, 0.0}}
|
107
|
+
Window, 0x600000384850, {{0.0, 0.0}, {414.0, 736.0}}
|
108
|
+
Other, 0x600000384920, traits: 8589934592, {{0.0, 0.0}, {414.0, 736.0}}
|
109
|
+
Other, 0x6000003849f0, traits: 8589934592, {{0.0, 736.0}, {414.0, 226.0}}
|
110
|
+
Window, 0x600000384ac0, {{0.0, 0.0}, {414.0, 736.0}}
|
111
|
+
StatusBar, 0x600000384b90, {{0.0, 0.0}, {414.0, 20.0}}
|
112
|
+
Other, 0x600000384c60, {{0.0, 0.0}, {414.0, 20.0}}
|
113
|
+
Other, 0x600000384d30, {{0.0, 0.0}, {414.0, 20.0}}
|
114
|
+
Other, 0x600000384e00, traits: 8388608, {{6.0, 0.0}, {39.0, 20.0}}
|
115
|
+
Other, 0x600000384ed0, traits: 8388608, {{50.0, 0.0}, {14.0, 20.0}}, label: '3 of 3 Wi-Fi bars', value: SSID
|
116
|
+
Other, 0x600000384fa0, traits: 8389120, {{184.0, 0.0}, {50.0, 20.0}}, label: '5:04 PM'
|
117
|
+
Other, 0x600000385070, traits: 8388608, {{383.0, 0.0}, {26.0, 20.0}}, label: '-100% battery power'
|
118
118
|
Path to element:
|
119
|
-
→Application,
|
119
|
+
→Application, 0x60000019fbd0, pid: 74050, {{0.0, 0.0}, {414.0, 736.0}}, label: 'myTargetDemo'
|
120
120
|
Query chain:
|
121
|
-
→Find: Application "ru.mail.adman"
|
121
|
+
→Find: Application "ru.mail.adman" 0x6000000a3540
|
122
122
|
Output: {
|
123
|
-
Application,
|
123
|
+
Application, 0x60000019fbd0, pid: 74050, {{0.0, 0.0}, {414.0, 736.0}}, label: 'myTargetDemo'
|
124
124
|
}
|
125
125
|
|
126
126
|
|
data/lib/skeleton.rb
CHANGED
data/lib/skeleton/android.rb
CHANGED
@@ -5,11 +5,15 @@ class Android < Base
|
|
5
5
|
CLASS = 'class'.freeze
|
6
6
|
ID = {
|
7
7
|
java: :id,
|
8
|
-
ruby: :id
|
8
|
+
ruby: :id,
|
9
|
+
javascript: :id,
|
10
|
+
python: :find_element_by_id
|
9
11
|
}.freeze
|
10
12
|
XPATH = {
|
11
13
|
java: :xpath,
|
12
|
-
ruby: :xpath
|
14
|
+
ruby: :xpath,
|
15
|
+
javascript: :xpath,
|
16
|
+
python: :find_element_by_xpath
|
13
17
|
}.freeze
|
14
18
|
|
15
19
|
attr_accessor :platform, :udid
|
@@ -79,8 +83,16 @@ class Android < Base
|
|
79
83
|
ruby = @language.ruby(snake_method_name: snake_style(method_name),
|
80
84
|
locator_type: locator_type,
|
81
85
|
locator_value: locator_value)
|
86
|
+
python = @language.python(snake_method_name: snake_style(method_name),
|
87
|
+
locator_type: locator_type,
|
88
|
+
locator_value: locator_value)
|
89
|
+
js = @language.js(camel_method_name: camel_style(method_name),
|
90
|
+
locator_type: locator_type,
|
91
|
+
locator_value: locator_value)
|
82
92
|
save(code: java, format: Language::JAVA)
|
83
93
|
save(code: ruby, format: Language::RUBY)
|
94
|
+
save(code: python, format: Language::PYTHON)
|
95
|
+
save(code: js, format: Language::JAVASCRIPT)
|
84
96
|
end
|
85
97
|
|
86
98
|
def page_source
|
data/lib/skeleton/ios.rb
CHANGED
@@ -1,11 +1,15 @@
|
|
1
1
|
class IOS < Base
|
2
2
|
ACC_ID = {
|
3
3
|
java: :AccessibilityId,
|
4
|
-
ruby: :accessibility_id
|
4
|
+
ruby: :accessibility_id,
|
5
|
+
javascript: :id,
|
6
|
+
python: :find_element_by_accessibility_id
|
5
7
|
}.freeze
|
6
8
|
NSPREDICATE = {
|
7
9
|
java: :iOSNsPredicateString,
|
8
|
-
ruby: :predicate
|
10
|
+
ruby: :predicate,
|
11
|
+
javascript: :predicate,
|
12
|
+
python: :find_element_by_ios_predicate
|
9
13
|
}.freeze
|
10
14
|
IDENTIFIER = 'identifier'.freeze
|
11
15
|
LABEL = 'label'.freeze
|
@@ -90,8 +94,16 @@ class IOS < Base
|
|
90
94
|
ruby = @language.ruby(snake_method_name: snake_style(method_name),
|
91
95
|
locator_type: locator_type,
|
92
96
|
locator_value: locator_value)
|
97
|
+
python = @language.python(snake_method_name: snake_style(method_name),
|
98
|
+
locator_type: locator_type,
|
99
|
+
locator_value: locator_value)
|
100
|
+
js = @language.js(camel_method_name: camel_style(method_name),
|
101
|
+
locator_type: locator_type,
|
102
|
+
locator_value: locator_value)
|
93
103
|
save(code: java, format: Language::JAVA)
|
94
104
|
save(code: ruby, format: Language::RUBY)
|
105
|
+
save(code: python, format: Language::PYTHON)
|
106
|
+
save(code: js, format: Language::JAVASCRIPT)
|
95
107
|
end
|
96
108
|
|
97
109
|
def page_source
|
data/lib/skeleton/languages.rb
CHANGED
@@ -1,7 +1,8 @@
|
|
1
1
|
class Language
|
2
|
-
JAVA = 'java'
|
3
|
-
RUBY = 'rb'
|
4
|
-
PYTHON = 'py'
|
2
|
+
JAVA = 'java'.freeze
|
3
|
+
RUBY = 'rb'.freeze
|
4
|
+
PYTHON = 'py'.freeze
|
5
|
+
JAVASCRIPT = 'js'.freeze
|
5
6
|
|
6
7
|
def java(camel_method_name:, locator_type:, locator_value:)
|
7
8
|
<<~JAVA
|
@@ -21,13 +22,32 @@ class Language
|
|
21
22
|
RUBY
|
22
23
|
end
|
23
24
|
|
25
|
+
def python(snake_method_name:, locator_type:, locator_value:)
|
26
|
+
<<~PYTHON
|
27
|
+
def #{snake_method_name}(self):
|
28
|
+
return self.driver.#{locator_type[:python]}("#{locator_value})"
|
29
|
+
|
30
|
+
PYTHON
|
31
|
+
end
|
32
|
+
|
33
|
+
def js(camel_method_name:, locator_type:, locator_value:)
|
34
|
+
<<~JS
|
35
|
+
function #{camel_method_name}() {
|
36
|
+
return driver.elements("#{locator_type[:javascript]}", "#{locator_value}");
|
37
|
+
}
|
38
|
+
|
39
|
+
JS
|
40
|
+
end
|
41
|
+
|
24
42
|
def type(format)
|
25
43
|
case format
|
26
|
-
when 'ruby'
|
44
|
+
when 'ruby', 'rb'
|
27
45
|
RUBY
|
28
46
|
when 'java'
|
29
47
|
JAVA
|
30
|
-
when '
|
48
|
+
when 'javascript', 'js'
|
49
|
+
JAVASCRIPT
|
50
|
+
when 'python', 'py'
|
31
51
|
PYTHON
|
32
52
|
else
|
33
53
|
"I haven't this language format"
|
data/lib/skeleton/root.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
class Base
|
2
|
-
|
3
|
-
|
4
|
-
|
2
|
+
ROOT_DIR = File.expand_path('..', Dir.pwd)
|
3
|
+
#ROOT_DIR = "#{`gem environment gemdir`.strip}" \
|
4
|
+
# "/gems/#{Skeleton::GEM_NAME}-#{Skeleton::VERSION}"
|
5
5
|
end
|
data/lib/skeleton/version.rb
CHANGED