gloo 5.3.8 → 6.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.
Files changed (88) hide show
  1. checksums.yaml +4 -4
  2. data/.DS_Store +0 -0
  3. data/CLAUDE.md +83 -0
  4. data/lib/VERSION +1 -1
  5. data/lib/VERSION_NOTES +14 -0
  6. data/lib/gloo/app/engine.rb +57 -13
  7. data/lib/gloo/app/engine_context.rb +1 -1
  8. data/lib/gloo/app/info.rb +0 -1
  9. data/lib/gloo/app/log.rb +1 -1
  10. data/lib/gloo/app/platform.rb +2 -2
  11. data/lib/gloo/app/prompt.rb +1 -0
  12. data/lib/gloo/app/settings.rb +0 -5
  13. data/lib/gloo/app/table.rb +1 -1
  14. data/lib/gloo/convert/nilclass_to_datetime.rb +1 -1
  15. data/lib/gloo/convert/nilclass_to_integer.rb +1 -3
  16. data/lib/gloo/convert/nilclass_to_string.rb +0 -2
  17. data/lib/gloo/convert/nilclass_to_time.rb +1 -1
  18. data/lib/gloo/convert/string_to_decimal.rb +1 -1
  19. data/lib/gloo/core/dictionary.rb +16 -22
  20. data/lib/gloo/core/event_manager.rb +19 -0
  21. data/lib/gloo/core/here.rb +2 -1
  22. data/lib/gloo/core/literal.rb +1 -1
  23. data/lib/gloo/core/obj.rb +5 -1
  24. data/lib/gloo/core/obj_finder.rb +0 -1
  25. data/lib/gloo/core/pn.rb +4 -2
  26. data/lib/gloo/exec/exec_env.rb +0 -2
  27. data/lib/gloo/exec/runner.rb +7 -2
  28. data/lib/gloo/expr/l_decimal.rb +1 -1
  29. data/lib/gloo/expr/l_string.rb +1 -1
  30. data/lib/gloo/expr/op_eq.rb +3 -1
  31. data/lib/gloo/expr/op_gt.rb +3 -0
  32. data/lib/gloo/expr/op_gteq.rb +3 -0
  33. data/lib/gloo/expr/op_ineq.rb +3 -0
  34. data/lib/gloo/expr/op_lt.rb +3 -0
  35. data/lib/gloo/expr/op_lteq.rb +3 -0
  36. data/lib/gloo/objs/basic/alias.rb +1 -1
  37. data/lib/gloo/objs/basic/boolean.rb +1 -1
  38. data/lib/gloo/objs/basic/decimal.rb +22 -1
  39. data/lib/gloo/objs/basic/integer.rb +19 -1
  40. data/lib/gloo/objs/basic/string_generator.rb +4 -7
  41. data/lib/gloo/objs/basic/untyped.rb +1 -1
  42. data/lib/gloo/objs/ctrl/each_child.rb +0 -2
  43. data/lib/gloo/objs/ctrl/function.rb +2 -5
  44. data/lib/gloo/objs/ctrl/repeat.rb +1 -2
  45. data/lib/gloo/objs/dt/datetime.rb +19 -8
  46. data/lib/gloo/objs/dt/dt_tools.rb +101 -21
  47. data/lib/gloo/objs/dt/time.rb +17 -1
  48. data/lib/gloo/objs/str_utils/cipher.rb +8 -11
  49. data/lib/gloo/objs/str_utils/outline.rb +0 -2
  50. data/lib/gloo/objs/system/erb.rb +5 -6
  51. data/lib/gloo/objs/system/file_handle.rb +18 -2
  52. data/lib/gloo/objs/system/system.rb +5 -11
  53. data/lib/gloo/objs/web/http_get.rb +6 -12
  54. data/lib/gloo/objs/web/http_post.rb +5 -31
  55. data/lib/gloo/objs/web/json.rb +1 -1
  56. data/lib/gloo/objs/web/uri.rb +2 -2
  57. data/lib/gloo/persist/disc_mech.rb +2 -2
  58. data/lib/gloo/persist/file_loader.rb +1 -1
  59. data/lib/gloo/persist/file_saver.rb +2 -2
  60. data/lib/gloo/persist/persist_man.rb +12 -8
  61. data/lib/gloo/plugin/callback.rb +1 -1
  62. data/lib/gloo/plugin/ext_manager.rb +1 -1
  63. data/lib/gloo/plugin/lib_manager.rb +1 -1
  64. data/lib/gloo/verbs/execute.rb +0 -6
  65. data/lib/gloo/verbs/files.rb +0 -1
  66. data/lib/gloo/verbs/help.rb +0 -16
  67. data/lib/gloo/verbs/list.rb +1 -1
  68. data/lib/gloo/verbs/load.rb +1 -1
  69. data/lib/gloo/verbs/show.rb +1 -1
  70. data/lib/gloo/verbs/throw.rb +55 -0
  71. data/test.gloo/ctrl/each.test.gloo +39 -0
  72. data/test.gloo/dt/date.test.gloo +1 -1
  73. data/test.gloo/dt/datetime.test.gloo +61 -0
  74. data/test.gloo/dt/time.test.gloo +14 -1
  75. data/test.gloo/lang/dt_comparisons.test.gloo +124 -0
  76. data/test.gloo/lang/exceptions.test.gloo +63 -0
  77. data/test.gloo/lang/gloo_sys.test.gloo +15 -0
  78. data/test.gloo/objs/alias.test.gloo +24 -0
  79. data/test.gloo/objs/decimal.test.gloo +38 -0
  80. data/test.gloo/objs/erb.test.gloo +35 -0
  81. data/test.gloo/objs/int.test.gloo +14 -0
  82. data/test.gloo/objs/string.test.gloo +44 -0
  83. data/test.gloo/verbs/create.test.gloo +14 -0
  84. data/test.gloo/verbs/invoke.test.gloo +20 -0
  85. data/test.gloo/verbs/unless.test.gloo +22 -0
  86. metadata +15 -4
  87. data/lib/gloo/utils/format.rb +0 -21
  88. data/lib/gloo/utils/words.rb +0 -19
@@ -37,10 +37,7 @@ module Gloo
37
37
  # Returns nil if there is none.
38
38
  #
39
39
  def uri_value
40
- uri = find_child URL
41
- return nil unless uri
42
-
43
- return uri.value
40
+ return find_child_value URL
44
41
  end
45
42
 
46
43
  #
@@ -50,7 +47,7 @@ module Gloo
50
47
  def body_as_json
51
48
  h = {}
52
49
 
53
- body = find_child BODY
50
+ body = find_child_resolve_alias BODY
54
51
  body.children.each do |child|
55
52
  child_val = Gloo::Objs::Alias.resolve_alias( @engine, child )
56
53
  h[ child.name ] = child_val.value
@@ -63,8 +60,8 @@ module Gloo
63
60
  # Set the result of the API call.
64
61
  #
65
62
  def update_result( data )
66
- r = find_child RESULT
67
- return nil unless r
63
+ r = find_child_resolve_alias RESULT
64
+ return unless r
68
65
 
69
66
  r.set_value data
70
67
  end
@@ -142,26 +139,6 @@ module Gloo
142
139
  end
143
140
  end
144
141
 
145
- # #
146
- # # Post the content to the endpoint.
147
- # #
148
- # def self.post_json_1( url, body, use_ssl = true )
149
- # # Structure the request
150
- # uri = URI.parse( url )
151
- #
152
- # request = Net::HTTP::Post.new( uri.path )
153
- # request.content_type = 'application/json'
154
- # request.body = body
155
- # n = Net::HTTP.new( uri.host, uri.port )
156
- # n.use_ssl = use_ssl
157
- #
158
- # # Send the payload to the endpoint.
159
- # result = n.start { |http| http.request( request ) }
160
- # @engine.log.debug result.code
161
- # @engine.log.debug result.message
162
- # return result.body
163
- # end
164
-
165
142
  # ---------------------------------------------------------------------
166
143
  # Private functions
167
144
  # ---------------------------------------------------------------------
@@ -172,10 +149,7 @@ module Gloo
172
149
  # Should we skip SSL verification during the request?
173
150
  #
174
151
  def skip_ssl_verify?
175
- skip = find_child SKIP_SSL_VERIFY
176
- return false unless skip
177
-
178
- return skip.value
152
+ return find_child_value( SKIP_SSL_VERIFY ) || false
179
153
  end
180
154
 
181
155
  end
@@ -106,7 +106,7 @@ module Gloo
106
106
  end
107
107
  parent = pn.resolve
108
108
 
109
- h = convert_obj_to_hash( parent )
109
+ h = Json.convert_obj_to_hash( parent )
110
110
  json = JSON.parse( h.to_json )
111
111
  json = JSON.pretty_generate( json )
112
112
 
@@ -62,7 +62,7 @@ module Gloo
62
62
  #
63
63
  def msg_get_cert_expires
64
64
  return unless value
65
- o = value
65
+
66
66
  uri = URI( value )
67
67
  response = Net::HTTP.start( uri.host, uri.port, :use_ssl => true )
68
68
  cert = response.peer_cert
@@ -143,7 +143,7 @@ module Gloo
143
143
 
144
144
 
145
145
  # ---------------------------------------------------------------------
146
- # Helper functiont to open a URL
146
+ # Helper function to open a URL
147
147
  # ---------------------------------------------------------------------
148
148
 
149
149
  #
@@ -2,9 +2,9 @@
2
2
  # Copyright:: Copyright (c) 2022 Eric Crane. All rights reserved.
3
3
  #
4
4
  # Disc based mechanism for files.
5
- # Provides interaction between the persistance classes and the OS
5
+ # Provides interaction between the persistence classes and the OS
6
6
  # file and folder system.
7
- # This class might be overiden elsewhere to provide other mechanism.
7
+ # This class might be overridden elsewhere to provide other mechanism.
8
8
  # For example, in gloo-web, there will be a db based mechanism.
9
9
  #
10
10
 
@@ -19,7 +19,7 @@ module Gloo
19
19
  #
20
20
  def initialize( engine, pn )
21
21
  @engine = engine
22
- @mech = @engine.platform.getFileMech( @engine )
22
+ @mech = @engine.platform.get_file_mech( @engine )
23
23
  @pn = pn
24
24
  @tabs = 0
25
25
  @obj = nil
@@ -1,7 +1,7 @@
1
1
  # Author:: Eric Crane (mailto:eric.crane@mac.com)
2
2
  # Copyright:: Copyright (c) 2019 Eric Crane. All rights reserved.
3
3
  #
4
- # Helper class used to save an object to a file..
4
+ # Helper class used to save an object to a file.
5
5
  #
6
6
 
7
7
  module Gloo
@@ -13,7 +13,7 @@ module Gloo
13
13
  #
14
14
  def initialize( engine, pn, obj )
15
15
  @engine = engine
16
- @mech = @engine.platform.getFileMech( @engine )
16
+ @mech = @engine.platform.get_file_mech( @engine )
17
17
  @pn = pn
18
18
  @obj = obj
19
19
  end
@@ -1,7 +1,7 @@
1
1
  # Author:: Eric Crane (mailto:eric.crane@mac.com)
2
2
  # Copyright:: Copyright (c) 2019 Eric Crane. All rights reserved.
3
3
  #
4
- # The persistance manager.
4
+ # The persistence manager.
5
5
  # Keeps a collection of object-file mappings, and then
6
6
  # uses mappings to know how/where to save updated objects.
7
7
  #
@@ -13,12 +13,12 @@ module Gloo
13
13
  attr_reader :maps, :mech
14
14
 
15
15
  #
16
- # Contructor for the persistence manager.
16
+ # Constructor for the persistence manager.
17
17
  #
18
18
  def initialize( engine )
19
19
  @engine = engine
20
20
  @maps = []
21
- @mech = @engine.platform.getFileMech( @engine )
21
+ @mech = @engine.platform.get_file_mech( @engine )
22
22
  end
23
23
 
24
24
  #
@@ -58,10 +58,14 @@ module Gloo
58
58
 
59
59
  pns.each do |pn|
60
60
  @engine.log.debug "Load file(s) at: #{pn}"
61
- fs = Gloo::Persist::FileStorage.new( @engine, pn )
62
- fs.load
63
- @maps << fs
64
- @engine.event_manager.on_load fs.obj
61
+ begin
62
+ fs = Gloo::Persist::FileStorage.new( @engine, pn )
63
+ fs.load
64
+ @maps << fs
65
+ @engine.event_manager.on_load fs.obj
66
+ rescue => ex
67
+ @engine.handle_exception( ex )
68
+ end
65
69
  end
66
70
  end
67
71
 
@@ -104,7 +108,7 @@ module Gloo
104
108
  @engine.event_manager.on_reload fs.obj
105
109
  end
106
110
 
107
- # Acutal unloading is done in the engine.restart.
111
+ # Actual unloading is done in the engine.restart.
108
112
  @engine.restart
109
113
  end
110
114
 
@@ -16,7 +16,7 @@ module Gloo
16
16
  # Register a verb.
17
17
  #
18
18
  def register_verb( verb_class )
19
- @engine.log.debug "Registering verb: #{verb_class} from callbackup helper"
19
+ @engine.log.debug "Registering verb: #{verb_class} from callback helper"
20
20
  @engine.dictionary.register_verb_post_start( verb_class )
21
21
  end
22
22
 
@@ -18,7 +18,7 @@ module Gloo
18
18
  def initialize( engine )
19
19
  @engine = engine
20
20
  @extensions = {}
21
- @engine.log.debug 'extension manager intialized...'
21
+ @engine.log.debug 'extension manager initialized...'
22
22
  end
23
23
 
24
24
  #
@@ -19,7 +19,7 @@ module Gloo
19
19
  def initialize( engine )
20
20
  @engine = engine
21
21
  @libraries = {}
22
- @engine.log.debug 'library manager intialized...'
22
+ @engine.log.debug 'library manager initialized...'
23
23
  end
24
24
 
25
25
  #
@@ -32,13 +32,7 @@ module Gloo
32
32
  exec cmd
33
33
  end
34
34
 
35
- # pid = spawn cmd
36
- # Process.wait pid
37
35
  @engine.log.debug "done executing cmd: #{cmd}"
38
-
39
- # system expr.evaluate #, chdir: Dir.pwd
40
- # `#{expr.evaluate}`
41
- # exec expr.evaluate
42
36
  end
43
37
 
44
38
  #
@@ -18,7 +18,6 @@ module Gloo
18
18
  return unless @engine.persist_man.maps
19
19
 
20
20
  @engine.persist_man.maps.each do |map|
21
- # puts "#{map.obj.name} - #{map.pn}"
22
21
  @engine.log.show "#{map.obj.name} - #{map.pn}"
23
22
  end
24
23
  @engine.heap.it.set_to @engine.persist_man.maps.count
@@ -84,13 +84,6 @@ module Gloo
84
84
  end
85
85
 
86
86
  #
87
- # Show all keywords: verbs and objects.
88
- #
89
- def show_keywords
90
- @engine.dictionary.show_keywords
91
- end
92
-
93
- #
94
87
  # Show default help.
95
88
  # No parameters were given.
96
89
  #
@@ -111,8 +104,6 @@ module Gloo
111
104
  # Dispatch the help to the right place.
112
105
  #
113
106
  def dispatch( opts )
114
- # return if dispatch_help_page( opts )
115
-
116
107
  @engine.log.debug 'looking for help topic'
117
108
  cmd = DISPATCH[ opts.to_sym ]
118
109
  if cmd
@@ -123,13 +114,6 @@ module Gloo
123
114
  end
124
115
  end
125
116
 
126
- #
127
- # Show application settings.
128
- #
129
- def show_settings
130
- @engine.settings.show
131
- end
132
-
133
117
  #
134
118
  # Report an error with the inline help.
135
119
  #
@@ -111,7 +111,7 @@ module Gloo
111
111
  end
112
112
 
113
113
  # Last chance: use the default
114
- return 2
114
+ return ' '
115
115
  end
116
116
 
117
117
  end
@@ -1,7 +1,7 @@
1
1
  # Author:: Eric Crane (mailto:eric.crane@mac.com)
2
2
  # Copyright:: Copyright (c) 2019 Eric Crane. All rights reserved.
3
3
  #
4
- # Save an object to a file or other persistance mechcanism.
4
+ # Load an object from a file or other persistence mechanism.
5
5
  #
6
6
 
7
7
  module Gloo
@@ -53,7 +53,7 @@ module Gloo
53
53
  expr = Gloo::Expr::Expression.new( @engine, @params.tokens )
54
54
  val = expr.evaluate
55
55
  color = val.to_sym
56
- return @engine.platform.getColorizedString( str, color )
56
+ return @engine.platform.get_colorized_string( str, color )
57
57
  end
58
58
  return str
59
59
  end
@@ -0,0 +1,55 @@
1
+ # Author:: Eric Crane (mailto:eric.crane@mac.com)
2
+ # Copyright:: Copyright (c) 2026 Eric Crane. All rights reserved.
3
+ #
4
+ # Deliberately raise a Ruby exception, to exercise the on_exception
5
+ # handling pipeline (eg. for testing).
6
+ #
7
+
8
+ module Gloo
9
+ module Verbs
10
+ class Throw < Gloo::Core::Verb
11
+
12
+ KEYWORD = 'throw'.freeze
13
+ KEYWORD_SHORT = 'throw'.freeze
14
+ DEFAULT_MSG = 'Thrown by throw verb'.freeze
15
+
16
+ #
17
+ # Run the verb.
18
+ #
19
+ def run
20
+ raise message
21
+ end
22
+
23
+ #
24
+ # Get the Verb's keyword.
25
+ #
26
+ def self.keyword
27
+ return KEYWORD
28
+ end
29
+
30
+ #
31
+ # Get the Verb's keyword shortcut.
32
+ #
33
+ def self.keyword_shortcut
34
+ return KEYWORD_SHORT
35
+ end
36
+
37
+ # ---------------------------------------------------------------------
38
+ # Private functions
39
+ # ---------------------------------------------------------------------
40
+
41
+ private
42
+
43
+ #
44
+ # Get the message to throw, evaluating an expression if one is given.
45
+ #
46
+ def message
47
+ return DEFAULT_MSG unless @tokens.params&.any?
48
+
49
+ expr = Gloo::Expr::Expression.new( @engine, @tokens.params )
50
+ return expr.evaluate
51
+ end
52
+
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,39 @@
1
+ #
2
+ # Each and repeat control object tests
3
+ #
4
+
5
+ tests [can] :
6
+ ctrl [can] :
7
+ each [can] :
8
+
9
+ count [int] : 0
10
+
11
+ wrd [each] :
12
+ word [string] :
13
+ IN [string] : one two three
14
+ do [script] :
15
+ eval ^^.count + 1
16
+ put it into ^^.count
17
+
18
+ rpt [repeat] :
19
+ times [int] : 3
20
+ index [int] : 0
21
+ do [script] :
22
+ eval ^^.count + 1
23
+ put it into ^^.count
24
+
25
+ each_word [test] :
26
+ description [string] : Count words with each word
27
+ on_test [script] :
28
+ put 0 into ^^.count
29
+ tell ^^.wrd to run
30
+ eval ^^.count = 3
31
+ assert "expected 3 words counted"
32
+
33
+ repeat_n_times [test] :
34
+ description [string] : Repeat a script n times
35
+ on_test [script] :
36
+ put 0 into ^^.count
37
+ tell ^^.rpt to run
38
+ eval ^^.count = 3
39
+ assert "expected repeat to run 3 times"
@@ -1,5 +1,5 @@
1
1
  #
2
- # Boolean tests
2
+ # Date tests
3
3
  #
4
4
 
5
5
  tests [can] :
@@ -0,0 +1,61 @@
1
+ #
2
+ # Datetime tests
3
+ #
4
+
5
+ tests [can] :
6
+ dt [can] :
7
+ datetime [can] :
8
+
9
+ d [dt] :
10
+
11
+ now [test] :
12
+ description [string] : Get the current datetime
13
+ on_test [script] :
14
+ check ^^.d for blank?
15
+ assert "expected new datetime to be blank"
16
+
17
+ tell ^^.d to now
18
+ check ^^.d for blank?
19
+ refute "expected datetime to not be blank after now"
20
+
21
+ is_today [test] :
22
+ description [string] : Check if datetime is today
23
+ on_test [script] :
24
+ tell ^^.d to now
25
+ tell ^^.d to is_today
26
+ assert "expected current datetime to be today"
27
+
28
+ is_past [test] :
29
+ description [string] : Check if datetime is in the past
30
+ on_test [script] :
31
+ tell ^^.d to now
32
+ tell ^^.d to is_past
33
+ refute "expected current datetime to not be in the past"
34
+
35
+ put 'yesterday' into ^^.d
36
+ tell ^^.d to is_past
37
+ assert "expected yesterday to be in the past"
38
+
39
+ is_future [test] :
40
+ description [string] : Check if datetime is in the future
41
+ on_test [script] :
42
+ tell ^^.d to now
43
+ tell ^^.d to is_future
44
+ refute "expected current datetime to not be in the future"
45
+
46
+ put 'tomorrow' into ^^.d
47
+ tell ^^.d to is_future
48
+ assert "expected tomorrow to be in the future"
49
+
50
+ format [test] :
51
+ description [string] : Format a datetime
52
+ f [dt] :
53
+ on_test [script] :
54
+ put '2025.10.15 2:30:00 PM' into ^.f
55
+ tell ^.f to format
56
+ eval it = '2025-10-15 14:30:00'
57
+ assert "expected formatted datetime to match"
58
+
59
+ tell ^.f to format ('%m/%d/%Y')
60
+ eval it = '10/15/2025'
61
+ assert "expected formatted datetime to match"
@@ -1,5 +1,5 @@
1
1
  #
2
- # Boolean tests
2
+ # Time tests
3
3
  #
4
4
 
5
5
  tests [can] :
@@ -74,3 +74,16 @@ tests [can] :
74
74
  eval it = ^^.t
75
75
  refute "expected am/pm to not be the same as the time"
76
76
 
77
+ format [test] :
78
+ description [string] : Format a time
79
+ f [time] :
80
+ on_test [script] :
81
+ put '2:30:00 PM' into ^.f
82
+ tell ^.f to format
83
+ eval it = '14:30:00'
84
+ assert "expected formatted time to match"
85
+
86
+ tell ^.f to format ('%I:%M %p')
87
+ eval it = '02:30 PM'
88
+ assert "expected formatted time to match"
89
+
@@ -0,0 +1,124 @@
1
+ #
2
+ # Date/time/datetime comparison operator tests
3
+ #
4
+
5
+ tests [can] :
6
+ lang [can] :
7
+ dt_comparisons [can] :
8
+
9
+ early_date [date] :
10
+ late_date [date] :
11
+ early_time [time] :
12
+ late_time [time] :
13
+ early_dt [datetime] :
14
+ late_dt [datetime] :
15
+
16
+ confirm_date_ops [test] :
17
+ description [string] : Confirm comparisons between two dates.
18
+ on_test [script] :
19
+ put '2025.01.01' into ^^.early_date
20
+ put '2025.06.01' into ^^.late_date
21
+
22
+ eval ^^.late_date > ^^.early_date
23
+ assert "expected late date to be greater than early date"
24
+
25
+ eval ^^.early_date < ^^.late_date
26
+ assert "expected early date to be less than late date"
27
+
28
+ eval ^^.early_date = ^^.early_date
29
+ assert "expected a date to equal itself"
30
+
31
+ eval ^^.early_date != ^^.late_date
32
+ assert "expected different dates to not be equal"
33
+
34
+ eval ^^.early_date >= ^^.early_date
35
+ assert "expected a date to be >= itself"
36
+
37
+ eval ^^.late_date <= ^^.early_date
38
+ refute "expected late date to not be <= early date"
39
+
40
+ confirm_time_ops [test] :
41
+ description [string] : Confirm comparisons between two times.
42
+ on_test [script] :
43
+ put '09:00:00 am' into ^^.early_time
44
+ put '05:00:00 pm' into ^^.late_time
45
+
46
+ eval ^^.late_time > ^^.early_time
47
+ assert "expected late time to be greater than early time"
48
+
49
+ eval ^^.early_time < ^^.late_time
50
+ assert "expected early time to be less than late time"
51
+
52
+ eval ^^.early_time = ^^.early_time
53
+ assert "expected a time to equal itself"
54
+
55
+ eval ^^.early_time != ^^.late_time
56
+ assert "expected different times to not be equal"
57
+
58
+ confirm_datetime_ops [test] :
59
+ description [string] : Confirm comparisons between two datetimes.
60
+ on_test [script] :
61
+ put '2025.01.01 09:00:00 am' into ^^.early_dt
62
+ put '2025.01.01 05:00:00 pm' into ^^.late_dt
63
+
64
+ eval ^^.late_dt > ^^.early_dt
65
+ assert "expected late datetime to be greater than early datetime"
66
+
67
+ eval ^^.early_dt < ^^.late_dt
68
+ assert "expected early datetime to be less than late datetime"
69
+
70
+ eval ^^.early_dt = ^^.early_dt
71
+ assert "expected a datetime to equal itself"
72
+
73
+ eval ^^.early_dt != ^^.late_dt
74
+ assert "expected different datetimes to not be equal"
75
+
76
+ confirm_date_vs_datetime [test] :
77
+ description [string] : Confirm a date coerces to midnight when compared to a datetime.
78
+ on_test [script] :
79
+ put '2025.06.01' into ^^.early_date
80
+ put '2025.06.01 12:00:00 am' into ^^.early_dt
81
+ put '2025.06.01 09:00:00 am' into ^^.late_dt
82
+
83
+ eval ^^.early_date = ^^.early_dt
84
+ assert "expected date to equal midnight of the same day"
85
+
86
+ eval ^^.late_dt > ^^.early_date
87
+ assert "expected later datetime to be greater than the date"
88
+
89
+ confirm_date_vs_time_is_false [test] :
90
+ description [string] : Confirm dates and times never compare as equal or ordered.
91
+ on_test [script] :
92
+ put '2025.06.01' into ^^.early_date
93
+ put '09:00:00 am' into ^^.early_time
94
+
95
+ eval ^^.early_date > ^^.early_time
96
+ refute "expected date > time to be false"
97
+
98
+ eval ^^.early_date = ^^.early_time
99
+ refute "expected date = time to be false"
100
+
101
+ eval ^^.early_date != ^^.early_time
102
+ refute "expected date != time to be false, since they can't be compared"
103
+
104
+ confirm_date_vs_loose_string [test] :
105
+ description [string] : Confirm a date can compare against a loosely formatted string.
106
+ on_test [script] :
107
+ put '2025.06.01' into ^^.late_date
108
+
109
+ eval ^^.late_date > "2025-01-01"
110
+ assert "expected date to be greater than a loosely parsed earlier date string"
111
+
112
+ eval ^^.late_date > "not a date"
113
+ refute "expected comparison against an unparseable string to be false"
114
+
115
+ confirm_date_vs_integer_is_false [test] :
116
+ description [string] : Confirm a date never compares as equal or ordered against an integer.
117
+ on_test [script] :
118
+ put '2025.06.01' into ^^.late_date
119
+
120
+ eval ^^.late_date > 5
121
+ refute "expected date > integer to be false"
122
+
123
+ eval ^^.late_date = 5
124
+ refute "expected date = integer to be false"