chione 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
+