citronella 0.0.4 → 1.0.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9020c7d6488bbbd5e67e35a1c939a2af5296736bbe99c45a6d8194ff347676aa
4
- data.tar.gz: 1fb3f63ea173a9c6ca720bfa945037bb8f6a595922929ee91972751e82d0239d
3
+ metadata.gz: 572a05603b535810328bd3d82612b5133810773ad46ca094daa2e92618d3087f
4
+ data.tar.gz: 913908e8bf7d28b6b9beb7a3ad86d4e9a9b6278b7250d11e0c43d711a60b6e25
5
5
  SHA512:
6
- metadata.gz: 9c52cdaeca3173c7d224f2d5f390b83d8b5e9835937bf1af3fa2e8a9ad05c03a1f16f02357b7a85f8052f36c598763a8b9a1551a8606964b78f53dee4bbd1194
7
- data.tar.gz: cfd8f9876408c022b04eab006ac24793473ee5a946bba6963446e2d7a66736e917def508b0528718ae7f6003b40da63dd43be16653d60128798a81aea3068165
6
+ metadata.gz: 51b581dcf93989fcf87d08c26ef7c9ba79182e390234d9d051b9e71005a64964feb34da34f862d51f7ec400dc47c184c46e274dbbd1eb8c8862f512ff746cfea
7
+ data.tar.gz: 562b3a4941affe127b9f7f0be4ec893d64b6bbe1c9a809cc8edf52c8ae4fc73d87a304915a00fc2def16c44e2578266b3f0dc351fc3dae2f370289e90845fd6a
data/Gemfile CHANGED
@@ -4,4 +4,5 @@ source "https://rubygems.org"
4
4
 
5
5
  git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
6
6
 
7
- gem "selenium-webdriver"
7
+ gem 'selenium-webdriver'
8
+ gem 'test-unit'
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Citronella
2
2
 
3
- [![Gem Version](https://badge.fury.io/rb/citronella.png)](http://badge.fury.io/rb/citronella)
3
+ [![Gem Version](https://badge.fury.io/rb/citronella.svg)](http://badge.fury.io/rb/citronella)
4
4
 
5
5
  webdriver extension with a page object wrapper.
6
6
 
@@ -17,6 +17,8 @@ class NavigationTest < Test::Unit::TestCase
17
17
  options = Selenium::WebDriver::Chrome::Options.new
18
18
  driver = Selenium::WebDriver.for :chrome, options: options
19
19
  @web = Citronella::Web::WebPage.new(driver)
20
+ @web.page = ContentsPage
21
+ @web.driver.navigate.to('https://rubygems.org')
20
22
  end
21
23
 
22
24
  def teardown
@@ -24,27 +26,28 @@ class NavigationTest < Test::Unit::TestCase
24
26
  end
25
27
 
26
28
  def test_navigation
27
- @web.page_object(ContentsPage.new.home_page, url=true)
28
- @web.page.releases_button.click
29
+ @web.page.home_page.releases_button.click
29
30
  assert_includes(@web.driver.title, 'Releases')
30
31
 
31
- @web.page.gems_button.click
32
+ @web.page.release_page.gems_button.click
32
33
  assert_includes(@web.driver.title, 'Gem')
33
34
 
34
- @web.page.sign_in_button.click
35
+ @web.page.gems_page.sign_in_button.click
35
36
  assert_includes(@web.driver.title, 'Sign in')
36
37
 
37
- @web.page.sign_up_button.click
38
+ @web.page.sign_in_page.sign_up_button.click
38
39
  assert_includes(@web.driver.title, 'Sign up')
39
40
 
40
- @web.page.guides_button.click
41
+ @web.page.sign_up_page.guides_button.click
41
42
  assert_includes(@web.driver.title, 'Guides')
42
43
 
43
- @web.page.blog_button.click
44
+ @web.page.guides_page.blog_button.click
44
45
  assert_includes(@web.driver.title, 'Blog')
45
46
  end
46
47
  end
47
48
  ```
49
+ ![alt terminal](https://github.com/heyclore/citronella/blob/main/ruby/screenshot/terminal.png?raw=true)
50
+
48
51
  Even though this module is mainly designed for the page object model, it can also be used without it for quick prototyping or mockups, etc.
49
52
  ```ruby
50
53
  require 'test/unit'
@@ -65,12 +68,14 @@ class PackageSearchTest < Test::Unit::TestCase
65
68
 
66
69
  def test_search_package
67
70
  @web.driver.navigate.to "https://rubygems.org/"
68
- @web.locate(id: 'home_query').get_element.send_keys('citronella')
69
- @web.locate(class: 'home__search__icon').get_element.click
71
+ @web.locate(id: 'home_query').send_keys('citronella')
72
+ @web.locate(class: 'home__search__icon').click
70
73
  assert(@web.locate(class: 'gems__gem__name').get_element.text, 'citronella')
71
74
  end
72
75
  end
73
76
  ```
77
+ ![alt terminal](https://github.com/heyclore/citronella/blob/main/ruby/screenshot/terminal2.png?raw=true)
78
+
74
79
  ___
75
80
  ## Install Package
76
81
 
@@ -81,7 +86,7 @@ gem install citronella
81
86
  ___
82
87
  ## Documentation
83
88
 
84
- There are only three modules imported in this package:
89
+ There are only two modules imported in this package:
85
90
 
86
91
  * The first module is for the tests.
87
92
 
@@ -103,25 +108,84 @@ class NavigationTest < Test::Unit::TestCase
103
108
  end
104
109
  ```
105
110
 
106
- * The second and third modules are for the page object model.
111
+ * The last module is for the page object model.
107
112
 
108
- ```python
113
+ ```ruby
109
114
  require 'citronella'
110
- require_relative '../contents_page'
115
+ require_relative '../components/header_menu'
111
116
 
112
- class HomePage < ContentsPage.new.header_menu
113
- @url = "https://rubygems.org/"
117
+ class HomePage
118
+ include HeaderMenu
114
119
 
115
120
  def search_button
116
- ui(class: 'home__search__icon', page: ContentsPage.new.search_page)
121
+ ui(class: 'home__search__icon')
117
122
  end
118
123
 
119
124
  def code_link_button
120
- ui(css: 'div.nav--v > a:nth-child(3)', page: Citronella::Dummy::PlaceholderPage)
125
+ ui(css: 'div.nav--v > a:nth-child(3)')
121
126
  end
122
127
  end
123
128
  ```
124
129
 
130
+ ___
131
+ ## Page Object Design / Strategy
132
+ see full [Page object](https://github.com/heyclore/citronella/tree/main/ruby/examples/page_object/pages) example
133
+ ```ruby
134
+ require "selenium-webdriver"
135
+ require 'citronella'
136
+
137
+ module HeaderMenu
138
+ def home_logo
139
+ ui(class: 'header__logo')
140
+ end
141
+
142
+ def search_input
143
+ ui(id: 'home_query')
144
+ end
145
+
146
+ def gems_button
147
+ ui(css: 'a[href="/gems"]')
148
+ end
149
+ end
150
+
151
+ class HomePage
152
+ include HeaderMenu
153
+
154
+ def search_button
155
+ ui(class: 'home__search__icon')
156
+ end
157
+
158
+ def code_link_button
159
+ ui(css: 'div.nav--v > a:nth-child(3)')
160
+ end
161
+ end
162
+
163
+ class SearchPage
164
+ include HeaderMenu
165
+
166
+ def search_lists
167
+ ui(class: 'gems__gem__name')
168
+ end
169
+ end
170
+
171
+ class ContentsPage
172
+ def home_page
173
+ HomePage
174
+ end
175
+
176
+ def search_page
177
+ SearchPage
178
+ end
179
+ end
180
+
181
+ options = Selenium::WebDriver::Chrome::Options.new
182
+ driver = Selenium::WebDriver.for :chrome, options: options
183
+ web = Citronella::Web::WebPage.new(driver)
184
+ web.page = ContentsPage
185
+ web.driver.navigate.to('https://rubygems.org')
186
+ web.page.home_page.search_input.send_keys('citronella', return_key=true)
187
+ puts web.page.search_page.search_list.get_element.text
188
+ ```
125
189
  ___
126
190
  ## Usage
127
191
 
@@ -137,27 +201,25 @@ ___
137
201
  ###### Method Lists:
138
202
  | Method Name | Args* | Kwargs** | Note |
139
203
  | ------------------ |:-----------:|:----------------:|:----:|
140
- | driver | None | None | return selenium `webdriver` object |
141
- | locate | None | how: what | similar as`driver.get_element` args |
142
- | page_object | Page Object | url `bool` | Page Object must contain `@url` variable with if using Kwargs** |
143
- | page | None | None | |
144
- | back | None | None | |
145
- | webdriver_wait | number(sec) | None | |
146
- | ready_state | number(sec) | None | execute javascript `document.readyState` manually |
204
+ | driver | - | - | return selenium `webdriver` object |
205
+ | locate | - | how: what | similar as`driver.get_element` as input & return [citronella.WebUi](https://github.com/heyclore/citronella/tree/main/ruby#citronellaui--citronellawebui)|
206
+ | page | Page Object | - | setter |
207
+ | page | - | - | getter |
208
+ | webdriver_wait | number(sec) | - | |
209
+ | ready_state | number(sec) | - | execute javascript `document.readyState` manually |
147
210
 
148
211
  ### citronella.ui / citronella.WebUi
149
212
 
150
213
  ###### Kwargs:
151
214
  - how: what
152
- - page_object (optional)
153
215
 
154
216
  ###### Method Lists:
155
217
  | Method Name | Args* | Kwargs** | Note |
156
218
  | ------------- |:------:|:------------------:|:----:|
157
- | send_keys | text | clear `bool`, return_key `bool`, switch_page `bool` | |
158
- | click | None | switch_page `bool` | |
159
- | get_element | None | None | |
160
- | get_elements | None | None | |
219
+ | send_keys | text | clear `bool`, return_key `bool` | |
220
+ | click | - | - | |
221
+ | get_element | - | - | |
222
+ | get_elements | - | - | |
161
223
 
162
224
 
163
225
  ## Testing powered by
data/citronella.gemspec CHANGED
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = 'citronella'
3
- s.version = '0.0.4'
3
+ s.version = '1.0.1'
4
4
 
5
5
  s.authors = ['heyclore']
6
6
  s.email = 'cloore@gmail.com'
data/lib/citronella.rb CHANGED
@@ -23,4 +23,3 @@
23
23
 
24
24
  require_relative 'web_page'
25
25
  require_relative 'ui'
26
- require_relative 'placeholder_page'
data/lib/logger.rb CHANGED
@@ -25,8 +25,14 @@ require 'logger'
25
25
 
26
26
  module Citronella
27
27
  module Log
28
+ # A wrapper for UI methods.
29
+ #
30
+ # @param [Boolean] logger Flag indicating whether to log actions.
31
+ # @param [String] class_name The name of the class.
32
+ # @param [String] function_name The name of the function.
33
+ # @param [String] name The name of the action.
34
+ #
28
35
  def self.logger(logger, class_name, function_name, name)
29
- """This is a logger method."""
30
36
  if logger
31
37
  Logger.new(STDOUT, level: Logger::INFO).info("#{class_name} => #{function_name} => #{name}")
32
38
  end
@@ -26,20 +26,32 @@ require_relative 'web_ui.rb'
26
26
  module Citronella
27
27
  module Wrapper
28
28
  class PageDecorator
29
- """This is a page decorator class."""
30
- def initialize(driver, webdriver_wait, pages, logger)
29
+ # A wrapper for page object class.
30
+ #
31
+ # @param [Webdriver] driver The web driver object.
32
+ # @param [Integer] webdriver_wait The timeout for webdriver wait.
33
+ # @param [PageObject] page The page object class.
34
+ # @param [Boolean] logger A flag indicating whether to log actions.
35
+ #
36
+ def initialize(driver, webdriver_wait, page, logger)
31
37
  @driver = driver
32
38
  @webdriver_wait = webdriver_wait
33
- @pages = pages
39
+ @page = page
34
40
  @logger = logger
35
41
  end
36
42
 
43
+ # Looks up the attribute/method name inside the page object.
44
+ #
45
+ # @return [PageDecorator, WebUi]
46
+ #
37
47
  def method_missing(attr)
38
- """look up the attr / method name inside page object."""
39
- original_method = @pages.current_page.new.method(attr)
48
+ original_method = @page.new.method(attr)
40
49
  args = original_method.call
41
- Citronella::Ui::WebUi.new(@driver, @webdriver_wait, @pages, @logger,
42
- args.last, args.first, attr, @pages.current_page.name)
50
+ if args.instance_of?(Class)
51
+ return PageDecorator.new(@driver, @webdriver_wait, args, @logger)
52
+ end
53
+ Citronella::Ui::WebUi.new(@driver, @webdriver_wait, @logger,
54
+ args, attr, @page.name)
43
55
  end
44
56
  end
45
57
  end
data/lib/ui.rb CHANGED
@@ -21,22 +21,13 @@
21
21
  #SOFTWARE.
22
22
 
23
23
 
24
+ # A wrapper for driver.find_element or driver.find_elements.
25
+ #
26
+ # @overload ui(args)
27
+ # @param locator [Symbol] The locator type.
28
+ # @param value [String] The locator value.
29
+ # @return [Citronella::Ui::WebUi] The web element object.
30
+ #
24
31
  def ui(args)
25
- """
26
- forward the data to page decorator and wrap into WebUi class.
27
-
28
- Args:
29
- by
30
-
31
- Kwarg:
32
- page(optional)
33
-
34
- Usage:
35
- without reference / page object. ui(name: 'q')
36
- with reference / page object. ui(id: 'submit', UserMenuPage)
37
-
38
- page are reference for the next page object if the element redirect to
39
- another page with WebUi click and send_keys(enter key) from input form.
40
- """
41
- return args.delete(:page), args
32
+ args
42
33
  end
data/lib/web_page.rb CHANGED
@@ -21,107 +21,89 @@
21
21
  #SOFTWARE.
22
22
 
23
23
 
24
- require_relative 'page_tab'
25
24
  require_relative 'page_decorator'
26
25
  require_relative 'web_ui'
27
26
 
28
27
  module Citronella
29
28
  module Web
29
+ # An object class that is used across the tests.
30
+ # `webdriver_wait` is set to '10' seconds by default.
31
+ # `logger` is set to 'true' by default.
32
+ #
33
+ # @param [Webdriver] driver The web driver object.
34
+ # @param [Integer] webdriver_wait The timeout for webdriver wait.
35
+ # @param [Boolean] logger A flag indicating whether to log actions.
36
+ #
37
+ # Usage:
38
+ # driver = Selenium::WebDriver.for :chrome
39
+ # web = WebPage.new(driver)
40
+ #
30
41
  class WebPage
31
- """
32
- an object class that use across the tests.
33
- webdriver_wait is set '10' seconds by default
34
- logger is set 'True' by default
35
-
36
- Args:
37
- driver
38
- Kwargs (optional):
39
- webdriver_wait
40
- logger
41
-
42
- Usage:
43
- driver = Selenium::WebDriver.for :chrome
44
- web = WebPage(driver)
45
- """
46
42
  def initialize(driver, webdriver_wait:10, logger:true)
47
43
  @driver = driver
48
44
  @webdriver_wait = webdriver_wait
49
- @pages = Citronella::PagesList.new
45
+ @page = nil
50
46
  @logger = logger
51
47
  end
52
48
 
49
+ # Returns the original Selenium driver.
50
+ #
51
+ # @return [Webdriver] The web driver object.
52
+ #
53
53
  def driver
54
- """return the original selenium / appium driver."""
55
54
  @driver
56
55
  end
57
56
 
58
- def page_object(new_page, url=false)
59
- """
60
- initialize page object module object, url kwargs is optional and
61
- it set to FALSE by default, it can be use if the page object have
62
- an @url variable.
63
- in selenium:
64
- it's equal as self.driver.navigate.to(url)
65
-
66
- Args:
67
- page_object_model
68
-
69
- Kwargs:
70
- url=true
71
-
72
- Usage:
73
- self.browser.page_object(Homepage)
74
- or
75
- self.browser.page_object(Homepage, url=true)
76
- """
77
- @pages.append(new_page)
78
- if url
79
- if not new_page.instance_variable_get(:@url)
80
- raise "Error: '@url' variable does not exist in #{new_page}"
81
- end
82
- @driver.navigate.to(new_page.instance_variable_get(:@url))
83
- end
84
- end
85
-
57
+ # Returns the wrapped page object model.
58
+ #
59
+ # @return [Citronella::Wrapper::PageDecorator] The page object model.
60
+ #
86
61
  def page
87
- """return last page object model."""
88
- Citronella::Wrapper::PageDecorator.new(@driver, @webdriver_wait, @pages, @logger)
62
+ Citronella::Wrapper::PageDecorator.new(@driver, @webdriver_wait, @page,
63
+ @logger)
89
64
  end
90
65
 
91
- def locate(args)
92
- """
93
- an alternative way for testing without page object and return WebUi
94
- class, but can't use page and back method and causing an error.
95
- good for quick prototype / write a tests.
96
-
97
- Args:
98
- by
99
- value
100
-
101
- Usage:
102
- web.ui(name: 'q').get_element.text
103
- web.ui(name: 'q').get_element.click
104
- """
105
- Citronella::Ui::WebUi.new(@driver, @webdriver_wait, @pages, @logger, args, nil,
106
- __method__.to_s, self.class.name.split('::').last.to_s)
66
+ # Sets the page object model.
67
+ #
68
+ # @param [PageObject] page The page object model.
69
+ #
70
+ def page=(page)
71
+ @page = page
107
72
  end
108
73
 
109
- def back
110
- """return to previous page and delete the last page object."""
111
- @driver.navigate.back
112
- @pages.pop
74
+ # An alternative way for testing without using page objects.
75
+ # It returns a WebUi class, but can't use `page` and may cause an error.
76
+ # It's good for quick prototypes or writing tests.
77
+ #
78
+ # @param [Hash] args The locator details.
79
+ # @return [Citronella::Ui::WebUi] The web element.
80
+ #
81
+ # Usage:
82
+ # web.ui(name: 'q').get_element.text
83
+ # web.ui(name: 'q').get_element.click
84
+ #
85
+ def locate(args)
86
+ Citronella::Ui::WebUi.new(@driver, @webdriver_wait, @logger, args,
87
+ args, __method__.to_s)
113
88
  end
114
89
 
90
+ # Executes JavaScript to wait for the page to fully load.
91
+ #
92
+ # @param [Integer] wait The number of times to check the page's ready state.
93
+ #
115
94
  def ready_state(wait)
116
- """execute javascript for page to fully load"""
117
95
  wait.times do |i|
118
- return if driver.execute_script("return document.readyState") == "complete"
96
+ return if driver.execute_script(
97
+ "return document.readyState") == "complete"
119
98
  sleep(1)
120
99
  end
121
100
  end
122
101
 
102
+ # Overrides the `webdriver_wait` value.
103
+ #
104
+ # @param [Integer] wait The new value for `webdriver_wait`.
105
+ #
123
106
  def webdriver_wait(wait)
124
- """override webdriver wait."""
125
107
  @webdriver_wait = wait
126
108
  end
127
109
  end
data/lib/web_ui.rb CHANGED
@@ -26,21 +26,31 @@ require_relative 'logger'
26
26
  module Citronella
27
27
  module Ui
28
28
  class WebUi
29
- """a wrapped object of a web element."""
30
- def initialize(driver, webdriver_wait, pages, logger, locator, new_page,
31
- function_name, class_name)
29
+ #
30
+ # @param [Webdriver] driver The web driver object.
31
+ # @param [Integer] webdriver_wait The timeout for webdriver wait.
32
+ # @param [Boolean] logger A flag indicating whether to log actions.
33
+ # @param [Hash] locator The locator for the web element.
34
+ # @param [String] function_name The name of the function.
35
+ # @param [String] class_name The name of the class.
36
+ #
37
+ def initialize(driver, webdriver_wait, logger, locator, function_name,
38
+ class_name)
32
39
  @driver = driver
33
40
  @wait = webdriver_wait
34
- @pages = pages
35
41
  @logger = logger
36
42
  @locator = locator
37
- @new_page = new_page
38
43
  @function_name = function_name
39
44
  @class_name = class_name
40
45
  end
41
46
 
47
+ # Waits for a web element to be available and returns it.
48
+ #
49
+ # @param [Webdriver] ele The web driver object.
50
+ # @param [Boolean] displayed Flag indicating whether to wait for the element to be displayed.
51
+ # @return [Webdriver::Element] The web element.
52
+ #
42
53
  private def webdriver_wait(ele, displayed=false)
43
- """return a web element or elements."""
44
54
  el = Selenium::WebDriver::Wait.new(timeout: @wait).until { ele }
45
55
  if displayed
46
56
  @wait.times do
@@ -51,41 +61,47 @@ module Citronella
51
61
  el
52
62
  end
53
63
 
54
- def send_keys(text, clear=false, return_key=false, switch_page=true)
55
- """custom webdriver send_keys with optional clear field."""
64
+ # Sends keys to the web element.
65
+ #
66
+ # @param [String] text The text to be sent.
67
+ # @param [Boolean] clear Flag indicating whether to clear the field before sending keys.
68
+ # @param [Boolean] return_key Flag indicating whether to send a return key.
69
+ #
70
+ def send_keys(text, clear=false, return_key=false)
56
71
  Citronella::Log.logger(@logger, @class_name, @function_name, __method__)
57
72
  el = webdriver_wait(@driver.find_element(@locator), displayed=true)
58
73
  el.send_keys text
59
74
 
60
75
  if return_key
61
76
  el.send_keys :return
62
-
63
- if @new_page and switch_page
64
- @pages.append(@new_page)
65
- end
66
77
  end
67
78
  end
68
79
 
69
- def click(switch_page=true)
70
- """click to web element."""
80
+ # Clicks on the web element.
81
+ #
82
+ def click
71
83
  Citronella::Log.logger(@logger, @class_name, @function_name, __method__)
72
84
  el = webdriver_wait(@driver.find_element(@locator), displayed=true)
73
85
  el.click
74
-
75
- if @new_page and switch_page
76
- @pages.append(@new_page)
77
- end
78
86
  end
79
87
 
88
+ # Returns a web element using find_element method.
89
+ #
90
+ # @return [Webdriver::Element] The web element.
91
+ #
80
92
  def get_element
81
- """return web element, equal as find_element."""
82
- Citronella::Log.logger(@logger, @class_name, @function_name, __method__.to_s)
93
+ Citronella::Log.logger(@logger, @class_name, @function_name,
94
+ __method__.to_s)
83
95
  webdriver_wait(@driver.find_element(@locator))
84
96
  end
85
97
 
98
+ # Returns a list of web elements using find_elements method.
99
+ #
100
+ # @return [Array<Webdriver::Element>] The list of web elements.
101
+ #
86
102
  def get_elements
87
- """return list of web element, equal as find_elements."""
88
- Citronella::Log.logger(@logger, @class_name, @function_name, __method__.to_s)
103
+ Citronella::Log.logger(@logger, @class_name, @function_name,
104
+ __method__.to_s)
89
105
  webdriver_wait(@driver.find_elements(@locator))
90
106
  end
91
107
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: citronella
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.4
4
+ version: 1.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - heyclore
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-03-12 00:00:00.000000000 Z
11
+ date: 2023-06-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: selenium-webdriver
@@ -36,8 +36,6 @@ files:
36
36
  - lib/citronella.rb
37
37
  - lib/logger.rb
38
38
  - lib/page_decorator.rb
39
- - lib/page_tab.rb
40
- - lib/placeholder_page.rb
41
39
  - lib/ui.rb
42
40
  - lib/web_page.rb
43
41
  - lib/web_ui.rb
data/lib/page_tab.rb DELETED
@@ -1,51 +0,0 @@
1
- #MIT License
2
- #
3
- #Copyright (c) 2023 Eko Purnomo
4
- #
5
- #Permission is hereby granted, free of charge, to any person obtaining a copy
6
- #of this software and associated documentation files (the "Software"), to deal
7
- #in the Software without restriction, including without limitation the rights
8
- #to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- #copies of the Software, and to permit persons to whom the Software is
10
- #furnished to do so, subject to the following conditions:
11
- #
12
- #The above copyright notice and this permission notice shall be included in all
13
- #copies or substantial portions of the Software.
14
- #
15
- #THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- #IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- #FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- #AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- #LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- #OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- #SOFTWARE.
22
-
23
-
24
- module Citronella
25
- class PagesList
26
- """This is a page page tab class."""
27
- def initialize
28
- @pages = []
29
- end
30
-
31
- def current_page
32
- """return the last page object stored."""
33
- @pages.last
34
- end
35
-
36
- def append(new_page)
37
- """store the page object in _pages."""
38
- @pages << new_page
39
- if @pages.length > 5
40
- @pages.shift
41
- end
42
- end
43
-
44
- def pop
45
- """delete the last item of the _pages lists."""
46
- return if @pages.empty?
47
- @pages.delete_at(-1)
48
- end
49
- end
50
- end
51
-
@@ -1,29 +0,0 @@
1
- #MIT License
2
- #
3
- #Copyright (c) 2023 Eko Purnomo
4
- #
5
- #Permission is hereby granted, free of charge, to any person obtaining a copy
6
- #of this software and associated documentation files (the "Software"), to deal
7
- #in the Software without restriction, including without limitation the rights
8
- #to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- #copies of the Software, and to permit persons to whom the Software is
10
- #furnished to do so, subject to the following conditions:
11
- #
12
- #The above copyright notice and this permission notice shall be included in all
13
- #copies or substantial portions of the Software.
14
- #
15
- #THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- #IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- #FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- #AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- #LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- #OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- #SOFTWARE.
22
-
23
-
24
- module Citronella
25
- module Dummy
26
- class PlaceholderPage
27
- end
28
- end
29
- end