11package dev .delivercraft .paint ;
22
3- import static org .assertj .core .api .Assertions .assertThat ;
4- import static org .assertj .core .api .Assertions .assertThatIllegalArgumentException ;
5-
6- import java .util .stream .Stream ;
7-
83import dev .delivercraft .io .CapturingLineWriter ;
94import dev .delivercraft .io .LineWriter ;
105import dev .delivercraft .io .StubLineReader ;
149import org .junit .jupiter .params .provider .MethodSource ;
1510import org .junit .jupiter .params .provider .ValueSource ;
1611
12+ import java .util .stream .Stream ;
13+
14+ import static org .assertj .core .api .Assertions .assertThat ;
15+ import static org .assertj .core .api .Assertions .assertThatIllegalArgumentException ;
16+
1717class PaintCalculatorTest {
1818
1919 private static final String VALID_LENGTH = "18" ;
@@ -36,59 +36,82 @@ class PaintCalculatorTest {
3636
3737 private static final String WIDTH_PROMPT = "What is the width of the room in feet? " ;
3838
39+ private static final String SHAPE_MENU = "Select room shape: 1) Rectangular 2) Round" ;
40+
41+ private static final String RADIUS_PROMPT = "What is the radius of the room in feet? " ;
42+
43+ private static final String RECTANGULAR_SHAPE = "1" ;
44+
45+ private static final String TEN_FEET = "10" ;
46+
47+ private static final String INVALID_LENGTH_OUTPUT =
48+ SHAPE_MENU + System .lineSeparator () + LENGTH_PROMPT ;
49+
50+ private static final String INVALID_WIDTH_OUTPUT =
51+ SHAPE_MENU + System .lineSeparator () + LENGTH_PROMPT + WIDTH_PROMPT ;
52+
3953 @ Test
4054 void calculatePaint_GivenExampleDimensions_ShouldDisplayGallonsAndArea () {
4155 LineWriter lineWriter = new CapturingLineWriter ();
42- PaintCalculator calculator = new PaintCalculator (new StubLineReader (VALID_LENGTH , VALID_WIDTH ), lineWriter );
56+ PaintCalculator calculator = new PaintCalculator (
57+ new StubLineReader (RECTANGULAR_SHAPE , VALID_LENGTH , VALID_WIDTH ), lineWriter );
4358
4459 calculator .calculatePaint ();
4560
46- assertThat (lineWriter ).hasToString (LENGTH_PROMPT + WIDTH_PROMPT
61+ assertThat (lineWriter ).hasToString (SHAPE_MENU + System .lineSeparator ()
62+ + LENGTH_PROMPT + WIDTH_PROMPT
4763 + "You will need to purchase 2 gallons of paint to cover 360 square feet."
4864 + System .lineSeparator ());
4965 }
5066
5167 @ Test
5268 void calculatePaint_GivenSmallCeiling_ShouldUseSingularGallon () {
5369 LineWriter lineWriter = new CapturingLineWriter ();
54- PaintCalculator calculator = new PaintCalculator (new StubLineReader ("10" , "10" ), lineWriter );
70+ PaintCalculator calculator = new PaintCalculator (
71+ new StubLineReader (RECTANGULAR_SHAPE , TEN_FEET , TEN_FEET ), lineWriter );
5572
5673 calculator .calculatePaint ();
5774
58- assertThat (lineWriter ).hasToString (LENGTH_PROMPT + WIDTH_PROMPT
75+ assertThat (lineWriter ).hasToString (SHAPE_MENU + System .lineSeparator ()
76+ + LENGTH_PROMPT + WIDTH_PROMPT
5977 + "You will need to purchase 1 gallon of paint to cover 100 square feet."
6078 + System .lineSeparator ());
6179 }
6280
6381 @ Test
6482 void calculatePaint_GivenFractionalDimensions_ShouldDisplayExactDecimalArea () {
6583 LineWriter lineWriter = new CapturingLineWriter ();
66- PaintCalculator calculator = new PaintCalculator (new StubLineReader ("10.5" , "10.1" ), lineWriter );
84+ PaintCalculator calculator = new PaintCalculator (
85+ new StubLineReader (RECTANGULAR_SHAPE , "10.5" , "10.1" ), lineWriter );
6786
6887 calculator .calculatePaint ();
6988
70- assertThat (lineWriter ).hasToString (LENGTH_PROMPT + WIDTH_PROMPT
89+ assertThat (lineWriter ).hasToString (SHAPE_MENU + System .lineSeparator ()
90+ + LENGTH_PROMPT + WIDTH_PROMPT
7191 + "You will need to purchase 1 gallon of paint to cover 106.05 square feet."
7292 + System .lineSeparator ());
7393 }
7494
7595 @ Test
7696 void calculatePaint_GivenAreaJustOverOneGallon_ShouldRoundGallonsUp () {
7797 LineWriter lineWriter = new CapturingLineWriter ();
78- PaintCalculator calculator = new PaintCalculator (new StubLineReader ("35.1" , "10" ), lineWriter );
98+ PaintCalculator calculator = new PaintCalculator (
99+ new StubLineReader (RECTANGULAR_SHAPE , "35.1" , "10" ), lineWriter );
79100
80101 calculator .calculatePaint ();
81102
82- assertThat (lineWriter ).hasToString (LENGTH_PROMPT + WIDTH_PROMPT
103+ assertThat (lineWriter ).hasToString (SHAPE_MENU + System .lineSeparator ()
104+ + LENGTH_PROMPT + WIDTH_PROMPT
83105 + "You will need to purchase 2 gallons of paint to cover 351 square feet."
84106 + System .lineSeparator ());
85107 }
86108
87109 @ ParameterizedTest
88110 @ MethodSource ("invalidInputFlows" )
89- void calculatePaint_GivenInvalidInput_ShouldFailFast (String length , String width , String expectedOutput ) {
111+ void calculatePaint_GivenInvalidInput_ShouldFailFast (String shape , String length , String width ,
112+ String expectedOutput ) {
90113 LineWriter lineWriter = new CapturingLineWriter ();
91- PaintCalculator calculator = new PaintCalculator (new StubLineReader (length , width ), lineWriter );
114+ PaintCalculator calculator = new PaintCalculator (new StubLineReader (shape , length , width ), lineWriter );
92115
93116 assertThatIllegalArgumentException ()
94117 .isThrownBy (calculator ::calculatePaint );
@@ -98,30 +121,67 @@ void calculatePaint_GivenInvalidInput_ShouldFailFast(String length, String width
98121
99122 private static Stream <Arguments > invalidInputFlows () {
100123 return Stream .of (
101- Arguments .of (EMPTY_INPUT , VALID_WIDTH , LENGTH_PROMPT ),
102- Arguments .of (null , VALID_WIDTH , LENGTH_PROMPT ),
103- Arguments .of (NON_NUMERIC_INPUT , VALID_WIDTH , LENGTH_PROMPT ),
104- Arguments .of (ZERO_INPUT , VALID_WIDTH , LENGTH_PROMPT ),
105- Arguments .of (NEGATIVE_INPUT , VALID_WIDTH , LENGTH_PROMPT ),
106- Arguments .of (SCIENTIFIC_INPUT , VALID_WIDTH , LENGTH_PROMPT ),
107- Arguments .of (SHORT_DECIMAL , VALID_WIDTH , LENGTH_PROMPT ),
108- Arguments .of (VALID_LENGTH , EMPTY_INPUT , LENGTH_PROMPT + WIDTH_PROMPT ),
109- Arguments .of (VALID_LENGTH , null , LENGTH_PROMPT + WIDTH_PROMPT ),
110- Arguments .of (VALID_LENGTH , NON_NUMERIC_INPUT , LENGTH_PROMPT + WIDTH_PROMPT ),
111- Arguments .of (VALID_LENGTH , ZERO_INPUT , LENGTH_PROMPT + WIDTH_PROMPT ),
112- Arguments .of (VALID_LENGTH , NEGATIVE_INPUT , LENGTH_PROMPT + WIDTH_PROMPT ),
113- Arguments .of (VALID_LENGTH , SCIENTIFIC_INPUT , LENGTH_PROMPT + WIDTH_PROMPT ),
114- Arguments .of (VALID_LENGTH , SHORT_DECIMAL , LENGTH_PROMPT + WIDTH_PROMPT ));
124+ Arguments .of (RECTANGULAR_SHAPE , EMPTY_INPUT , VALID_WIDTH , INVALID_LENGTH_OUTPUT ),
125+ Arguments .of (RECTANGULAR_SHAPE , null , VALID_WIDTH , INVALID_LENGTH_OUTPUT ),
126+ Arguments .of (RECTANGULAR_SHAPE , NON_NUMERIC_INPUT , VALID_WIDTH , INVALID_LENGTH_OUTPUT ),
127+ Arguments .of (RECTANGULAR_SHAPE , ZERO_INPUT , VALID_WIDTH , INVALID_LENGTH_OUTPUT ),
128+ Arguments .of (RECTANGULAR_SHAPE , NEGATIVE_INPUT , VALID_WIDTH , INVALID_LENGTH_OUTPUT ),
129+ Arguments .of (RECTANGULAR_SHAPE , SCIENTIFIC_INPUT , VALID_WIDTH , INVALID_LENGTH_OUTPUT ),
130+ Arguments .of (RECTANGULAR_SHAPE , SHORT_DECIMAL , VALID_WIDTH , INVALID_LENGTH_OUTPUT ),
131+ Arguments .of (RECTANGULAR_SHAPE , VALID_LENGTH , EMPTY_INPUT , INVALID_WIDTH_OUTPUT ),
132+ Arguments .of (RECTANGULAR_SHAPE , VALID_LENGTH , null , INVALID_WIDTH_OUTPUT ),
133+ Arguments .of (RECTANGULAR_SHAPE , VALID_LENGTH , NON_NUMERIC_INPUT , INVALID_WIDTH_OUTPUT ),
134+ Arguments .of (RECTANGULAR_SHAPE , VALID_LENGTH , ZERO_INPUT , INVALID_WIDTH_OUTPUT ),
135+ Arguments .of (RECTANGULAR_SHAPE , VALID_LENGTH , NEGATIVE_INPUT , INVALID_WIDTH_OUTPUT ),
136+ Arguments .of (RECTANGULAR_SHAPE , VALID_LENGTH , SCIENTIFIC_INPUT , INVALID_WIDTH_OUTPUT ),
137+ Arguments .of (RECTANGULAR_SHAPE , VALID_LENGTH , SHORT_DECIMAL , INVALID_WIDTH_OUTPUT ));
115138 }
116139
117140 @ ParameterizedTest
118141 @ ValueSource (strings = {"18" , " 18 " , "18.0" , "0.5" })
119142 void calculatePaint_GivenPlainDecimalInput_ShouldAcceptInput (String input ) {
120143 LineWriter lineWriter = new CapturingLineWriter ();
121- PaintCalculator calculator = new PaintCalculator (new StubLineReader (input , "20" ), lineWriter );
144+ PaintCalculator calculator = new PaintCalculator (
145+ new StubLineReader (RECTANGULAR_SHAPE , input , "20" ), lineWriter );
122146
123147 calculator .calculatePaint ();
124148
125149 assertThat (lineWriter .toString ()).contains ("You will need to purchase" );
126150 }
151+
152+ @ Test
153+ void calculatePaint_GivenRoundRoomSelection_ShouldCalculateCorrectArea () {
154+ LineWriter lineWriter = new CapturingLineWriter ();
155+ PaintCalculator calculator = new PaintCalculator (new StubLineReader ("2" , "10" ), lineWriter );
156+
157+ calculator .calculatePaint ();
158+
159+ assertThat (lineWriter ).hasToString (SHAPE_MENU + System .lineSeparator ()
160+ + RADIUS_PROMPT
161+ + "You will need to purchase 1 gallon of paint to cover 314.16 square feet."
162+ + System .lineSeparator ());
163+ }
164+
165+ @ ParameterizedTest
166+ @ ValueSource (strings = {"3" , "0" , "abc" , "" , " " })
167+ void calculatePaint_GivenInvalidShapeInput_ShouldThrowIllegalArgumentException (String invalidInput ) {
168+ LineWriter lineWriter = new CapturingLineWriter ();
169+ PaintCalculator calculator = new PaintCalculator (new StubLineReader (invalidInput ), lineWriter );
170+
171+ assertThatIllegalArgumentException ()
172+ .isThrownBy (calculator ::calculatePaint )
173+ .withMessage ("Please enter 1 or 2" );
174+ assertThat (lineWriter .toString ()).isEqualTo (SHAPE_MENU + System .lineSeparator ());
175+ }
176+
177+ @ Test
178+ void calculatePaint_GivenNullShapeInput_ShouldThrowIllegalArgumentException () {
179+ LineWriter lineWriter = new CapturingLineWriter ();
180+ PaintCalculator calculator = new PaintCalculator (() -> null , lineWriter );
181+
182+ assertThatIllegalArgumentException ()
183+ .isThrownBy (calculator ::calculatePaint )
184+ .withMessage ("Please enter 1 or 2" );
185+ assertThat (lineWriter .toString ()).isEqualTo (SHAPE_MENU + System .lineSeparator ());
186+ }
127187}
0 commit comments