Runtime assertions for Ruby literal.fun
ruby
5
fork

Configure Feed

Select the types of activity you want to include in your feed.

Add module that adds optional prop introspection methods

+217
+59
lib/literal/properties/introspection.rb
··· 1 + # frozen_string_literal: true 2 + 3 + module Literal::Properties::Introspection 4 + def positional_properties 5 + literal_properties.filter(&:positional?) 6 + end 7 + 8 + def keyword_properties 9 + literal_properties.filter(&:keyword?) 10 + end 11 + 12 + def required_properties 13 + literal_properties.filter(&:required?) 14 + end 15 + 16 + def required_positional_properties 17 + required_properties.filter(&:positional?) 18 + end 19 + 20 + def required_keyword_properties 21 + required_properties.filter(&:keyword?) 22 + end 23 + 24 + def optional_positional_properties 25 + positional_properties - required_positional_properties 26 + end 27 + 28 + def optional_keyword_properties 29 + keyword_properties - required_keyword_properties 30 + end 31 + 32 + def positional_property_names 33 + positional_properties.map(&:name) 34 + end 35 + 36 + def keyword_property_names 37 + keyword_properties.map(&:name) 38 + end 39 + 40 + def required_property_names 41 + required_properties.map(&:name) 42 + end 43 + 44 + def required_positional_property_names 45 + required_positional_properties.map(&:name) 46 + end 47 + 48 + def required_keyword_property_names 49 + required_keyword_properties.map(&:name) 50 + end 51 + 52 + def optional_positional_property_names 53 + optional_positional_properties.map(&:name) 54 + end 55 + 56 + def optional_keyword_property_names 57 + optional_keyword_properties.map(&:name) 58 + end 59 + end
+158
test/properties/introspection.test.rb
··· 1 + # frozen_string_literal: true 2 + 3 + class BasicIntrospection 4 + extend Literal::Properties 5 + extend Literal::Properties::Introspection 6 + 7 + prop :id, Integer, :positional 8 + prop :name, String, :positional 9 + prop :age, Integer 10 + prop :email, _Nilable(String) 11 + prop :friends, _Array(String), :* 12 + prop :options, _Hash(Symbol, String), :** 13 + prop :block, _Nilable(Proc), :& 14 + end 15 + 16 + class WithOptionals 17 + extend Literal::Properties 18 + extend Literal::Properties::Introspection 19 + 20 + prop :required_pos, String, :positional 21 + prop :optional_pos, String, :positional, default: "default" 22 + prop :optional_name, _Nilable(String), :positional 23 + prop :required_kw, Integer 24 + prop :optional_kw, Integer, default: 42 25 + prop :tags, _Array(String), default: -> { [] } 26 + prop :created_at, _Nilable(Time) 27 + end 28 + 29 + class EmptyWithIntrospection 30 + extend Literal::Properties 31 + extend Literal::Properties::Introspection 32 + end 33 + 34 + test "positional_properties returns all positional properties" do 35 + props = BasicIntrospection.positional_properties 36 + assert_equal props.map(&:name), [:id, :name] 37 + assert props.all?(&:positional?) 38 + end 39 + 40 + test "positional_property_names returns all positional property names" do 41 + names = BasicIntrospection.positional_property_names 42 + assert_equal names, [:id, :name] 43 + end 44 + 45 + test "keyword_properties returns all keyword properties" do 46 + props = BasicIntrospection.keyword_properties 47 + assert_equal props.map(&:name), [:age, :email] 48 + assert props.all?(&:keyword?) 49 + end 50 + 51 + test "keyword_property_names returns all keyword property names" do 52 + names = BasicIntrospection.keyword_property_names 53 + assert_equal names, [:age, :email] 54 + end 55 + 56 + test "required_properties returns all required properties" do 57 + props = BasicIntrospection.required_properties 58 + puts props.inspect 59 + assert_equal props.map(&:name), [:id, :name, :age] 60 + assert props.all?(&:required?) 61 + end 62 + 63 + test "required_property_names returns all required property names" do 64 + names = BasicIntrospection.required_property_names 65 + assert_equal names, [:id, :name, :age] 66 + end 67 + 68 + test "required_positional_properties returns only required positional properties" do 69 + props = BasicIntrospection.required_positional_properties 70 + assert_equal props.map(&:name), [:id, :name] 71 + assert props.all? { |p| p.required? && p.positional? } 72 + end 73 + 74 + test "required_positional_property_names returns only required positional property names" do 75 + names = BasicIntrospection.required_positional_property_names 76 + assert_equal names, [:id, :name] 77 + end 78 + 79 + test "required_keyword_properties returns only required keyword properties" do 80 + props = BasicIntrospection.required_keyword_properties 81 + assert_equal props.map(&:name), [:age] 82 + assert props.all? { |p| p.required? && p.keyword? } 83 + end 84 + 85 + test "required_keyword_property_names returns only required keyword property names" do 86 + names = BasicIntrospection.required_keyword_property_names 87 + assert_equal names, [:age] 88 + end 89 + 90 + test "optional_positional_properties returns positional properties that are not required" do 91 + props = WithOptionals.optional_positional_properties 92 + assert_equal props.map(&:name), [:optional_pos, :optional_name] 93 + assert props.all? { |p| p.positional? && !p.required? } 94 + end 95 + 96 + test "optional_positional_property_names returns optional positional property names" do 97 + names = WithOptionals.optional_positional_property_names 98 + assert_equal names, [:optional_pos, :optional_name] 99 + end 100 + 101 + test "optional_keyword_properties returns keyword properties that are not required" do 102 + props = WithOptionals.optional_keyword_properties 103 + assert_equal props.map(&:name), [:optional_kw, :tags, :created_at] 104 + assert props.all? { |p| p.keyword? && !p.required? } 105 + end 106 + 107 + test "optional_keyword_property_names returns optional keyword property names" do 108 + names = WithOptionals.optional_keyword_property_names 109 + assert_equal names, [:optional_kw, :tags, :created_at] 110 + end 111 + 112 + test "empty class returns empty arrays for all methods" do 113 + assert_equal EmptyWithIntrospection.positional_properties, [] 114 + assert_equal EmptyWithIntrospection.keyword_properties, [] 115 + assert_equal EmptyWithIntrospection.required_properties, [] 116 + assert_equal EmptyWithIntrospection.required_positional_properties, [] 117 + assert_equal EmptyWithIntrospection.required_keyword_properties, [] 118 + assert_equal EmptyWithIntrospection.optional_positional_properties, [] 119 + assert_equal EmptyWithIntrospection.optional_keyword_properties, [] 120 + 121 + assert_equal EmptyWithIntrospection.positional_property_names, [] 122 + assert_equal EmptyWithIntrospection.keyword_property_names, [] 123 + assert_equal EmptyWithIntrospection.required_property_names, [] 124 + assert_equal EmptyWithIntrospection.required_positional_property_names, [] 125 + assert_equal EmptyWithIntrospection.required_keyword_property_names, [] 126 + assert_equal EmptyWithIntrospection.optional_positional_property_names, [] 127 + assert_equal EmptyWithIntrospection.optional_keyword_property_names, [] 128 + end 129 + 130 + test "splat parameters are not included in positional or keyword properties" do 131 + positional_names = BasicIntrospection.positional_property_names 132 + refute positional_names.include?(:friends) 133 + 134 + keyword_names = BasicIntrospection.keyword_property_names 135 + refute keyword_names.include?(:options) 136 + end 137 + 138 + test "block parameters are not included in any property lists" do 139 + all_names = BasicIntrospection.positional_property_names + BasicIntrospection.keyword_property_names 140 + refute all_names.include?(:block) 141 + end 142 + 143 + test "nilable positional properties are considered optional" do 144 + required_names = WithOptionals.required_positional_property_names 145 + optional_names = WithOptionals.optional_positional_property_names 146 + 147 + assert_equal required_names, [:required_pos] 148 + assert_equal optional_names, [:optional_pos, :optional_name] 149 + end 150 + 151 + test "mixed property types with defaults and nilables" do 152 + assert_equal WithOptionals.positional_property_names, [:required_pos, :optional_pos, :optional_name] 153 + assert_equal WithOptionals.keyword_property_names, [:required_kw, :optional_kw, :tags, :created_at] 154 + assert_equal WithOptionals.required_positional_property_names, [:required_pos] 155 + assert_equal WithOptionals.required_keyword_property_names, [:required_kw] 156 + assert_equal WithOptionals.optional_positional_property_names, [:optional_pos, :optional_name] 157 + assert_equal WithOptionals.optional_keyword_property_names, [:optional_kw, :tags, :created_at] 158 + end