citronella 0.0.4 → 1.0.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9020c7d6488bbbd5e67e35a1c939a2af5296736bbe99c45a6d8194ff347676aa
4
- data.tar.gz: 1fb3f63ea173a9c6ca720bfa945037bb8f6a595922929ee91972751e82d0239d
3
+ metadata.gz: c7ef1f78d05ad8a27657474af4a584e56c30921d217f863cd85fb06e163f358a
4
+ data.tar.gz: 3e8992f2bdec5de5479ed4b62ca2b42feabacfce598c736fb117a9f41ef79967
5
5
  SHA512:
6
- metadata.gz: 9c52cdaeca3173c7d224f2d5f390b83d8b5e9835937bf1af3fa2e8a9ad05c03a1f16f02357b7a85f8052f36c598763a8b9a1551a8606964b78f53dee4bbd1194
7
- data.tar.gz: cfd8f9876408c022b04eab006ac24793473ee5a946bba6963446e2d7a66736e917def508b0528718ae7f6003b40da63dd43be16653d60128798a81aea3068165
6
+ metadata.gz: 9db842a70045cd3cd25592c9a18e27690aa3d22759b99abe7bc9823e16f49fe0cc1a5d45a3ab0c33381a41cb8728c3d844352ff8e9e520cdec64ea7b9f297889
7
+ data.tar.gz: c06316aef0e0343f3d3ee04598b481e047d5b0ef2c808750425e7cf3f76f766747247b00f2acbd11814f01c680228d48fa87b6551a549e197bd23b584d970b0e
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,23 +26,22 @@ 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
@@ -81,7 +82,7 @@ gem install citronella
81
82
  ___
82
83
  ## Documentation
83
84
 
84
- There are only three modules imported in this package:
85
+ There are only two modules imported in this package:
85
86
 
86
87
  * The first module is for the tests.
87
88
 
@@ -103,25 +104,84 @@ class NavigationTest < Test::Unit::TestCase
103
104
  end
104
105
  ```
105
106
 
106
- * The second and third modules are for the page object model.
107
+ * The last module is for the page object model.
107
108
 
108
- ```python
109
+ ```ruby
109
110
  require 'citronella'
110
- require_relative '../contents_page'
111
+ require_relative '../components/header_menu'
111
112
 
112
- class HomePage < ContentsPage.new.header_menu
113
- @url = "https://rubygems.org/"
113
+ class HomePage
114
+ include HeaderMenu
114
115
 
115
116
  def search_button
116
- ui(class: 'home__search__icon', page: ContentsPage.new.search_page)
117
+ ui(class: 'home__search__icon')
117
118
  end
118
119
 
119
120
  def code_link_button
120
- ui(css: 'div.nav--v > a:nth-child(3)', page: Citronella::Dummy::PlaceholderPage)
121
+ ui(css: 'div.nav--v > a:nth-child(3)')
121
122
  end
122
123
  end
123
124
  ```
124
125
 
126
+ ___
127
+ ## Page Object Design / Strategy
128
+ see full [Page object](https://github.com/heyclore/citronella/tree/main/ruby/examples/page_object/pages) example
129
+ ```ruby
130
+ require "selenium-webdriver"
131
+ require 'citronella'
132
+
133
+ module HeaderMenu
134
+ def home_logo
135
+ ui(class: 'header__logo')
136
+ end
137
+
138
+ def search_input
139
+ ui(id: 'home_query')
140
+ end
141
+
142
+ def gems_button
143
+ ui(css: 'a[href="/gems"]')
144
+ end
145
+ end
146
+
147
+ class HomePage
148
+ include HeaderMenu
149
+
150
+ def search_button
151
+ ui(class: 'home__search__icon')
152
+ end
153
+
154
+ def code_link_button
155
+ ui(css: 'div.nav--v > a:nth-child(3)')
156
+ end
157
+ end
158
+
159
+ class SearchPage
160
+ include HeaderMenu
161
+
162
+ def search_lists
163
+ ui(class: 'gems__gem__name')
164
+ end
165
+ end
166
+
167
+ class ContentsPage
168
+ def home_page
169
+ HomePage
170
+ end
171
+
172
+ def search_page
173
+ SearchPage
174
+ end
175
+ end
176
+
177
+ options = Selenium::WebDriver::Chrome::Options.new
178
+ driver = Selenium::WebDriver.for :chrome, options: options
179
+ web = Citronella::Web::WebPage.new(driver)
180
+ web.page = ContentsPage
181
+ web.driver.navigate.to('https://rubygems.org')
182
+ web.page.home_page.search_input.send_keys('citronella', return_key=true)
183
+ puts web.page.search_page.search_list.get_element.text
184
+ ```
125
185
  ___
126
186
  ## Usage
127
187
 
@@ -137,27 +197,25 @@ ___
137
197
  ###### Method Lists:
138
198
  | Method Name | Args* | Kwargs** | Note |
139
199
  | ------------------ |:-----------:|:----------------:|:----:|
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 |
200
+ | driver | - | - | return selenium `webdriver` object |
201
+ | locate | - | how: what | similar as`driver.get_element` as input & return [citronella.WebUi](https://github.com/heyclore/citronella/tree/main/ruby#citronellaui--citronellawebui)|
202
+ | page | Page Object | - | setter |
203
+ | page | - | - | getter |
204
+ | webdriver_wait | number(sec) | - | |
205
+ | ready_state | number(sec) | - | execute javascript `document.readyState` manually |
147
206
 
148
207
  ### citronella.ui / citronella.WebUi
149
208
 
150
209
  ###### Kwargs:
151
210
  - how: what
152
- - page_object (optional)
153
211
 
154
212
  ###### Method Lists:
155
213
  | Method Name | Args* | Kwargs** | Note |
156
214
  | ------------- |:------:|:------------------:|:----:|
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 | |
215
+ | send_keys | text | clear `bool`, return_key `bool` | |
216
+ | click | - | - | |
217
+ | get_element | - | - | |
218
+ | get_elements | - | - | |
161
219
 
162
220
 
163
221
  ## 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.0'
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,90 @@
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
+ __method__.to_s,
88
+ self.class.name.split('::').last.to_s)
113
89
  end
114
90
 
91
+ # Executes JavaScript to wait for the page to fully load.
92
+ #
93
+ # @param [Integer] wait The number of times to check the page's ready state.
94
+ #
115
95
  def ready_state(wait)
116
- """execute javascript for page to fully load"""
117
96
  wait.times do |i|
118
- return if driver.execute_script("return document.readyState") == "complete"
97
+ return if driver.execute_script(
98
+ "return document.readyState") == "complete"
119
99
  sleep(1)
120
100
  end
121
101
  end
122
102
 
103
+ # Overrides the `webdriver_wait` value.
104
+ #
105
+ # @param [Integer] wait The new value for `webdriver_wait`.
106
+ #
123
107
  def webdriver_wait(wait)
124
- """override webdriver wait."""
125
108
  @webdriver_wait = wait
126
109
  end
127
110
  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.0
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-02 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