chione 0.0.2

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.
@@ -0,0 +1,143 @@
1
+ #!/usr/bin/env rspec -cfd
2
+
3
+ require_relative '../spec_helper'
4
+
5
+ require 'chione/aspect'
6
+ require 'chione/component'
7
+
8
+
9
+ describe Chione::Aspect do
10
+
11
+ let( :location ) do
12
+ Class.new( Chione::Component ) do
13
+ field :x, default: 0
14
+ field :y, default: 0
15
+ end
16
+ end
17
+
18
+ let( :tags ) do
19
+ Class.new( Chione::Component ) do
20
+ field :tags, default: []
21
+ end
22
+ end
23
+
24
+ let( :color ) do
25
+ Class.new( Chione::Component ) do
26
+ field :hue, default: 0
27
+ field :shade, default: 0
28
+ field :value, default: 0
29
+ field :opacity, default: 0
30
+ end
31
+ end
32
+
33
+
34
+ it "doesn't have any default criteria" do
35
+ aspect = described_class.new
36
+ expect( aspect.one_of ).to be_empty
37
+ expect( aspect.all_of ).to be_empty
38
+ expect( aspect.none_of ).to be_empty
39
+ expect( aspect ).to be_empty
40
+ end
41
+
42
+
43
+ it "can be created with default criteria" do
44
+ aspect = described_class.with_all_of( tags, location )
45
+ expect( aspect.one_of ).to be_empty
46
+ expect( aspect.all_of.size ).to eq( 2 )
47
+ expect( aspect.all_of ).to include( tags, location )
48
+ expect( aspect.none_of ).to be_empty
49
+ end
50
+
51
+
52
+ it "can make a clone of itself with additional one_of criteria" do
53
+ aspect = described_class.new
54
+ clone = aspect.with_one_of( location, tags )
55
+ expect( clone ).to_not be( aspect )
56
+ expect( clone.one_of ).to include( location, tags )
57
+ expect( aspect.one_of ).to be_empty
58
+ end
59
+
60
+
61
+ it "can make a clone of itself with additional none_of criteria" do
62
+ aspect = described_class.with_none_of( location )
63
+ clone = aspect.with_none_of( tags )
64
+ expect( clone ).to_not be( aspect )
65
+ expect( clone.none_of ).to include( location, tags )
66
+ expect( aspect.none_of.size ).to eq( 1 )
67
+ expect( aspect.none_of ).to include( location )
68
+ end
69
+
70
+
71
+ it "can make a clone of itself with additional all_of criteria" do
72
+ aspect = described_class.with_all_of( color, location )
73
+ clone = aspect.with_all_of( tags )
74
+ expect( clone ).to_not be( aspect )
75
+ expect( clone.all_of.size ).to eq( 3 )
76
+ expect( clone.all_of ).to include( location, tags, color )
77
+ expect( aspect.all_of.size ).to eq( 2 )
78
+ expect( aspect.all_of ).to include( location, color )
79
+ end
80
+
81
+
82
+ it "supports a fluent interface" do
83
+ aspect = described_class.with_all_of( tags, location ).and_none_of( color )
84
+ expect( aspect.one_of ).to be_empty
85
+ expect( aspect.all_of.size ).to eq( 2 )
86
+ expect( aspect.all_of ).to include( tags, location )
87
+ expect( aspect.none_of.size ).to eq( 1 )
88
+ expect( aspect.none_of ).to include( color )
89
+ end
90
+
91
+
92
+ it "flattens Arrays passed to ::with_all_of" do
93
+ aspect = described_class.with_all_of([ tags, location ])
94
+
95
+ expect( aspect.all_of.size ).to eq( 2 )
96
+ expect( aspect.all_of ).to include( tags, location )
97
+ end
98
+
99
+
100
+ it "flattens Arrays passed to #with_all_of" do
101
+ aspect = described_class.new
102
+ aspect = aspect.with_all_of([ tags, location ])
103
+
104
+ expect( aspect.all_of.size ).to eq( 2 )
105
+ expect( aspect.all_of ).to include( tags, location )
106
+ end
107
+
108
+
109
+ it "flattens Arrays passed to ::with_one_of" do
110
+ aspect = described_class.with_one_of([ tags, location ])
111
+
112
+ expect( aspect.one_of.size ).to eq( 2 )
113
+ expect( aspect.one_of ).to include( tags, location )
114
+ end
115
+
116
+
117
+ it "flattens Arrays passed to #with_one_of" do
118
+ aspect = described_class.new
119
+ aspect = aspect.with_one_of([ tags, location ])
120
+
121
+ expect( aspect.one_of.size ).to eq( 2 )
122
+ expect( aspect.one_of ).to include( tags, location )
123
+ end
124
+
125
+
126
+ it "flattens Arrays passed to ::with_none_of" do
127
+ aspect = described_class.with_none_of([ tags, location ])
128
+
129
+ expect( aspect.none_of.size ).to eq( 2 )
130
+ expect( aspect.none_of ).to include( tags, location )
131
+ end
132
+
133
+
134
+ it "flattens Arrays passed to #with_none_of" do
135
+ aspect = described_class.new
136
+ aspect = aspect.with_none_of([ tags, location ])
137
+
138
+ expect( aspect.none_of.size ).to eq( 2 )
139
+ expect( aspect.none_of ).to include( tags, location )
140
+ end
141
+
142
+ end
143
+
@@ -0,0 +1,60 @@
1
+ #!/usr/bin/env rspec -cfd
2
+
3
+ require_relative '../spec_helper'
4
+
5
+ require 'chione/assemblage'
6
+ require 'chione/component'
7
+ require 'chione/entity'
8
+ require 'chione/world'
9
+
10
+ describe Chione::Assemblage do
11
+
12
+ let( :world ) { Chione::World.new }
13
+
14
+ let( :location_component ) do
15
+ Class.new( Chione::Component ) do
16
+ field :x, default: 0
17
+ field :y, default: 0
18
+ end
19
+ end
20
+
21
+ let( :tags_component ) do
22
+ Class.new( Chione::Component ) do
23
+ field :tags, default: []
24
+ end
25
+ end
26
+
27
+
28
+ it "acts as a factory for entities with pre-set components" do
29
+ assemblage = Module.new
30
+ assemblage.extend( described_class )
31
+ assemblage.add( location_component, x: 10, y: 8 )
32
+ assemblage.add( tags_component, tags: [:foo, :bar] )
33
+
34
+ entity = assemblage.construct_for( world )
35
+
36
+ expect( entity ).to be_a( Chione::Entity )
37
+ expect( entity.world ).to be( world )
38
+ expect( entity.components ).to include( location_component, tags_component )
39
+ end
40
+
41
+
42
+ it "can include other assemblages" do
43
+ general_assemblage = Module.new
44
+ general_assemblage.extend( described_class )
45
+ general_assemblage.add( location_component, x: 10, y: 8 )
46
+
47
+ specific_assemblage = Module.new
48
+ specific_assemblage.extend( described_class )
49
+ specific_assemblage.send( :include, general_assemblage )
50
+ specific_assemblage.add( tags_component, tags: [:foo, :bar] )
51
+
52
+ entity = specific_assemblage.construct_for( world )
53
+
54
+ expect( entity ).to be_a( Chione::Entity )
55
+ expect( entity.world ).to be( world )
56
+ expect( entity.components ).to include( location_component, tags_component )
57
+ end
58
+
59
+ end
60
+
@@ -0,0 +1,54 @@
1
+ #!/usr/bin/env rspec -cfd
2
+
3
+ require_relative '../spec_helper'
4
+
5
+ require 'chione/component'
6
+
7
+
8
+ describe Chione::Component do
9
+
10
+ describe "concrete subclasses" do
11
+
12
+ let( :component_subclass ) do
13
+ Class.new( described_class )
14
+ end
15
+
16
+
17
+ it "can declare fields" do
18
+ component_subclass.field( :x )
19
+ component_subclass.field( :y )
20
+
21
+ instance = component_subclass.new
22
+ expect( instance ).to respond_to( :x )
23
+ expect( instance ).to respond_to( :y )
24
+
25
+ expect( instance.x ).to be_nil
26
+ expect( instance.y ).to be_nil
27
+ end
28
+
29
+
30
+ it "can declare fields with default values" do
31
+ component_subclass.field( :x, default: 0 )
32
+ component_subclass.field( :y, default: 18 )
33
+
34
+ instance = component_subclass.new
35
+ expect( instance.x ).to eq( 0 )
36
+ expect( instance.y ).to eq( 18 )
37
+ end
38
+
39
+
40
+ it "uses a dup of the default if it's not an immediate object" do
41
+ component_subclass.field( :things, default: [] )
42
+
43
+ instance1 = component_subclass.new
44
+ instance2 = component_subclass.new
45
+
46
+ instance1.things << "a thing"
47
+
48
+ expect( instance2.things ).to be_empty
49
+ end
50
+
51
+ end
52
+
53
+ end
54
+
@@ -0,0 +1,109 @@
1
+ #!/usr/bin/env rspec -cfd
2
+
3
+ require_relative '../spec_helper'
4
+
5
+ require 'chione/entity'
6
+ require 'chione/component'
7
+
8
+
9
+ describe Chione::Entity do
10
+
11
+ let( :world ) { Chione::World.new }
12
+
13
+ let( :location_component ) do
14
+ Class.new( Chione::Component ) do
15
+ field :x, default: 0
16
+ field :y, default: 0
17
+ end
18
+ end
19
+
20
+ let( :tags_component ) do
21
+ Class.new( Chione::Component ) do
22
+ field :tags, default: []
23
+ end
24
+ end
25
+
26
+ let( :bounding_box_component ) do
27
+ Class.new( Chione::Component ) do
28
+ field :width, default: 1
29
+ field :height, default: 1
30
+ field :depth, default: 1
31
+ end
32
+ end
33
+
34
+
35
+ it "knows what world it was created for" do
36
+ expect( Chione::Entity.new(world).world ).to be( world )
37
+ end
38
+
39
+
40
+ it "uses the ID it's given in creation" do
41
+ entity = Chione::Entity.new( world, 'some-other-id' )
42
+ expect( entity.id ).to eq( 'some-other-id' )
43
+ end
44
+
45
+
46
+ it "generates an ID for itself if it isn't given one" do
47
+ entity = Chione::Entity.new( world )
48
+ expect( entity.id ).to be_a( String )
49
+ expect( entity.id.length ).to be >= 8
50
+
51
+ expect( Chione::Entity.new(world).id ).to_not eq( entity.id )
52
+ end
53
+
54
+
55
+ describe "concrete instance" do
56
+
57
+ let( :entity ) { Chione::Entity.new(world) }
58
+
59
+
60
+ it "can have components added to it" do
61
+ entity.add_component( location_component.new )
62
+ entity.add_component( tags_component.new )
63
+
64
+ expect( entity ).to have_component( location_component )
65
+ expect( entity ).to have_component( tags_component )
66
+ end
67
+
68
+
69
+ it "lets components be fetched from it" do
70
+ entity.add_component( location_component.new )
71
+ entity.add_component( tags_component.new )
72
+
73
+ expect(
74
+ entity.get_component( location_component )
75
+ ).to eq( entity.components[location_component] )
76
+ end
77
+
78
+
79
+ it "lets one of a list of components be fetched from it" do
80
+ entity.add_component( location_component.new )
81
+ entity.add_component( tags_component.new )
82
+
83
+ expect(
84
+ entity.get_component( bounding_box_component, location_component )
85
+ ).to eq( entity.components[location_component] )
86
+ end
87
+
88
+
89
+ it "raises a KeyError if it doesn't have a fetched component" do
90
+ entity.add_component( tags_component.new )
91
+
92
+ expect {
93
+ entity.get_component( location_component )
94
+ }.to raise_error( KeyError, /#{entity.id} doesn't have/i )
95
+ end
96
+
97
+
98
+ it "raises a KeyError if it doesn't have any of several fetched components" do
99
+ entity.add_component( tags_component.new )
100
+
101
+ expect {
102
+ entity.get_component( location_component, bounding_box_component )
103
+ }.to raise_error( KeyError, /#{entity.id} doesn't have any of/i )
104
+ end
105
+
106
+ end
107
+
108
+ end
109
+
@@ -0,0 +1,39 @@
1
+ #!/usr/bin/env rspec -cfd
2
+
3
+ require_relative '../spec_helper'
4
+
5
+ require 'chione/manager'
6
+ require 'chione/world'
7
+
8
+
9
+ describe Chione::Manager do
10
+
11
+ let( :world ) { Chione::World.new }
12
+
13
+
14
+ describe "concrete derivatives" do
15
+
16
+ let( :manager_class ) do
17
+ Class.new( described_class )
18
+ end
19
+
20
+ let( :manager ) { manager_class.new(world) }
21
+
22
+
23
+ it "are required to implement #start" do
24
+ expect {
25
+ manager.start
26
+ }.to raise_error( NotImplementedError, /does not implement/i )
27
+ end
28
+
29
+
30
+ it "are required to implement #stop" do
31
+ expect {
32
+ manager.stop
33
+ }.to raise_error( NotImplementedError, /does not implement/i )
34
+ end
35
+
36
+ end
37
+
38
+ end
39
+
@@ -0,0 +1,94 @@
1
+ #!/usr/bin/env rspec -cfd
2
+
3
+ require_relative '../spec_helper'
4
+
5
+ require 'chione/mixins'
6
+
7
+
8
+ describe Chione, "mixins" do
9
+
10
+ describe Chione::MethodUtilities, 'used to extend a class' do
11
+
12
+ let!( :extended_class ) do
13
+ klass = Class.new
14
+ klass.extend( Chione::MethodUtilities )
15
+ klass
16
+ end
17
+
18
+ it "can declare a class-level attribute reader" do
19
+ extended_class.singleton_attr_reader :foo
20
+ expect( extended_class ).to respond_to( :foo )
21
+ expect( extended_class ).to_not respond_to( :foo= )
22
+ expect( extended_class ).to_not respond_to( :foo? )
23
+ end
24
+
25
+ it "can declare a class-level attribute writer" do
26
+ extended_class.singleton_attr_writer :foo
27
+ expect( extended_class ).to_not respond_to( :foo )
28
+ expect( extended_class ).to respond_to( :foo= )
29
+ expect( extended_class ).to_not respond_to( :foo? )
30
+ end
31
+
32
+ it "can declare a class-level attribute reader and writer" do
33
+ extended_class.singleton_attr_accessor :foo
34
+ expect( extended_class ).to respond_to( :foo )
35
+ expect( extended_class ).to respond_to( :foo= )
36
+ expect( extended_class ).to_not respond_to( :foo? )
37
+ end
38
+
39
+ it "can declare a class-level alias" do
40
+ def extended_class.foo
41
+ return "foo"
42
+ end
43
+ extended_class.singleton_method_alias( :bar, :foo )
44
+
45
+ expect( extended_class.bar ).to eq( 'foo' )
46
+ end
47
+
48
+ it "can declare an instance attribute predicate method" do
49
+ extended_class.attr_predicate :foo
50
+ instance = extended_class.new
51
+
52
+ expect( instance ).to_not respond_to( :foo )
53
+ expect( instance ).to_not respond_to( :foo= )
54
+ expect( instance ).to respond_to( :foo? )
55
+
56
+ expect( instance.foo? ).to be_falsey
57
+
58
+ instance.instance_variable_set( :@foo, 1 )
59
+ expect( instance.foo? ).to be_truthy
60
+ end
61
+
62
+ it "can declare an instance attribute predicate and writer" do
63
+ extended_class.attr_predicate_accessor :foo
64
+ instance = extended_class.new
65
+
66
+ expect( instance ).to_not respond_to( :foo )
67
+ expect( instance ).to respond_to( :foo= )
68
+ expect( instance ).to respond_to( :foo? )
69
+
70
+ expect( instance.foo? ).to be_falsey
71
+
72
+ instance.foo = 1
73
+ expect( instance.foo? ).to be_truthy
74
+ end
75
+
76
+ it "can declare a class-level attribute predicate and writer" do
77
+ extended_class.singleton_predicate_accessor :foo
78
+ expect( extended_class ).to_not respond_to( :foo )
79
+ expect( extended_class ).to respond_to( :foo= )
80
+ expect( extended_class ).to respond_to( :foo? )
81
+ end
82
+
83
+ it "can declare a class-level predicate method" do
84
+ extended_class.singleton_predicate_reader :foo
85
+ expect( extended_class ).to_not respond_to( :foo )
86
+ expect( extended_class ).to_not respond_to( :foo= )
87
+ expect( extended_class ).to respond_to( :foo? )
88
+ end
89
+
90
+ end
91
+
92
+
93
+ end
94
+