master
  1require "rails_helper"
  2
  3describe User do
  4  describe "#create" do
  5    it "saves a new user to the database" do
  6      user = create(:user)
  7
  8      saved_user = User.find(user.id)
  9      expect(saved_user.username).to eql(user.username)
 10      expect(saved_user.email).to eql(user.email)
 11      expect(saved_user.password).to be_nil
 12    end
 13
 14    it "lowercases the username" do
 15      user = create(:user, username: "UpCASE")
 16      expect(user.reload.username).to eql("upcase")
 17    end
 18
 19    it "lowercases the email" do
 20      user = create(:user, email: FFaker::Internet.email.upcase)
 21      expect(user.reload.email).to eql(user.email.downcase)
 22    end
 23  end
 24
 25  describe "validations" do
 26    context "username" do
 27      it "is invalid when the username is missing" do
 28        user = User.new(username: nil)
 29        expect(user).to_not be_valid
 30        expect(user.errors[:username]).to_not be_empty
 31      end
 32
 33      it "is invalid if invalid characters are in the username" do
 34        user = User.new(username: "$()")
 35        expect(user).to_not be_valid
 36        expect(user.errors[:username]).to_not be_empty
 37      end
 38
 39      it "is invalid if the username is already taken" do
 40        create(:user, username: "blah", email: "blah@example.com")
 41        user = build(:user, username: "blah", email: "blahblah@example.com")
 42        expect(user).to_not be_valid
 43        expect(user.errors[:username]).to_not be_empty
 44      end
 45    end
 46
 47    describe "#email" do
 48      it "is invalid when the email is missing" do
 49        user = User.new(email: nil)
 50        expect(user).to_not be_valid
 51        expect(user.errors[:email]).to_not be_empty
 52      end
 53
 54      it "is invalid when the email is not in the correct format" do
 55        user = User.new(email: "blah")
 56        expect(user).to_not be_valid
 57        expect(user.errors[:email]).to_not be_empty
 58      end
 59
 60      it "is invalid if the email address is already registered" do
 61        create(:user, username: "blahblah", email: "blah@example.com")
 62        second_user = build(:user, username: "blah", email: "blah@example.com")
 63        expect(second_user).to_not be_valid
 64        expect(second_user.errors[:email]).to_not be_empty
 65      end
 66    end
 67
 68    describe "terms_and_conditions" do
 69      it "is invalid if terms and conditions is unchecked" do
 70        user = User.new(terms_and_conditions: false)
 71        expect(user).to_not be_valid
 72        expect(user.errors[:terms_and_conditions]).to_not be_empty
 73      end
 74    end
 75
 76    it "is valid when it is" do
 77      user = User.new(
 78        username: "coolio",
 79        email: "notblank@example.com",
 80        password: "legit",
 81        terms_and_conditions: "1")
 82      expect(user).to be_valid
 83    end
 84  end
 85
 86  describe "USERNAME_REGEX" do
 87    it "does not match" do
 88      expect(User::USERNAME_REGEX).to_not match("$username")
 89      expect(User::USERNAME_REGEX).to_not match("!username")
 90      expect(User::USERNAME_REGEX).to_not match("@username")
 91    end
 92
 93    it "matches" do
 94      expect(User::USERNAME_REGEX).to match("username")
 95      expect(User::USERNAME_REGEX).to match("user.name")
 96      expect(User::USERNAME_REGEX).to match("user_name")
 97      expect(User::USERNAME_REGEX).to match("user-name")
 98      expect(User::USERNAME_REGEX).to match("username1")
 99    end
100  end
101
102
103  describe "#to_param" do
104    it "returns the username as the uniq identifier" do
105      user = build(:user)
106      expect(user.to_param).to eql(user.username)
107    end
108  end
109
110  describe "#personal_record_for" do
111    include_context "stronglifts_program"
112    let(:user) { create(:user) }
113    let(:recommendation) { routine_a.recommendations.find_by(exercise: squat) }
114
115    before :each do
116      workout = user.workouts.create!(
117        routine: routine_a,
118        occurred_at: DateTime.now.utc
119      )
120      workout.train(squat, 201, repetitions: recommendation.repetitions)
121      workout.train(squat, 202, repetitions: recommendation.repetitions)
122      workout.train(squat, 210, repetitions: recommendation.repetitions - 1)
123      workout.train(squat, 204, repetitions: recommendation.repetitions)
124      workout.train(squat, 205, repetitions: recommendation.repetitions)
125    end
126
127    it "returns the users maximum amount of weight lifted" do
128      expect(user.personal_record_for(squat)).to eql(205.0)
129    end
130  end
131
132  describe "#begin_workout" do
133    subject { create(:user) }
134    let(:routine) { create(:routine) }
135    let(:today) { DateTime.now }
136
137    it "creates a new training session" do
138      result = subject.begin_workout(routine, today, 200)
139      expect(result).to be_persisted
140      expect(subject.workouts.count).to eql(1)
141      expect(subject.workouts.first).to eql(result)
142      expect(result.routine).to eql(routine)
143      expect(result.occurred_at).to eql(today.utc)
144      expect(result.body_weight).to eql(200.lbs)
145    end
146
147    it "returns the existing workout for that day" do
148      result = subject.begin_workout(routine, today, 200)
149      expect(subject.begin_workout(routine, today, 200)).to eql(result)
150    end
151
152    it "returns different sessions for different days" do
153      todays_result = subject.begin_workout(routine, today, 200)
154      tomorrows_result = subject.begin_workout(routine, DateTime.tomorrow, 200)
155      expect(todays_result).to_not eql(tomorrows_result)
156    end
157  end
158
159  describe "when destroying a training session" do
160    include_context "stronglifts_program"
161    subject { create(:user) }
162
163    it "removes all the associations" do
164      workout = subject.begin_workout(routine_a, Date.today, 200)
165      workout.train(squat, 200, repetitions: 5)
166      workout.train(squat, 200, repetitions: 5)
167      workout.train(squat, 200, repetitions: 5)
168      workout.train(squat, 200, repetitions: 5)
169      workout.train(squat, 200, repetitions: 5)
170
171      subject.workouts.destroy_all
172
173      expect(Workout.all).to be_empty
174      expect(ExerciseSet.all).to be_empty
175    end
176  end
177
178  describe "#profile" do
179    let(:user) { create(:user) }
180
181    it "creates a new profile" do
182      expect(user.profile).to be_present
183      expect(user.profile.other?).to be_truthy
184      expect(user.profile.social_tolerance).to be_nil
185    end
186  end
187
188  describe "#login" do
189    context "when credentials are correct" do
190      it "returns true" do
191        user = create(:user, password: "password", password_confirmation: "password")
192        result = User.login(user.email.upcase, "password")
193        expect(result).to be_instance_of(UserSession)
194        expect(result.user).to eql(user)
195      end
196
197      it "is case in-sensitive for username" do
198        user = create(:user, username: "upcase", password: "password", password_confirmation: "password")
199        result = User.login("UPcase", "password")
200        expect(result).to be_instance_of(UserSession)
201        expect(result.user).to eql(user)
202      end
203    end
204
205    context "when the email is not registered" do
206      it { expect(User.login("sofake@noteven.com", "password")).to be_falsey }
207    end
208
209    context "when the username is not registered" do
210      it { expect(User.login("sofake", "password")).to be_falsey }
211    end
212  end
213
214  describe "#add_to_inbox" do
215    include_context "stronglifts_program"
216    subject { create(:user) }
217    let(:email) { build(:email, :with_attachment) }
218
219    it "records the email" do
220      subject.add_to_inbox(email)
221      expect(subject.received_emails.count).to eql(1)
222      received_email = subject.received_emails.first
223      expect(received_email.to.map(&:symbolize_keys)).to match_array(email.to)
224      expect(received_email.from.symbolize_keys).to eql(email.from)
225      expect(received_email.subject).to eql(email.subject)
226      expect(received_email.body).to eql(email.body)
227    end
228  end
229
230  describe "#next_workout_for" do
231    subject { create(:user) }
232    let(:routine) { create(:routine) }
233    let(:body_weight) { rand(300) }
234
235    it "includes the body weight from the previous workout" do
236      create(:workout, user: subject, body_weight: body_weight)
237
238      workout = subject.next_workout_for(routine)
239      expect(workout.body_weight).to eql(body_weight)
240    end
241
242    it "uses the correct routine" do
243      workout = subject.next_workout_for(routine)
244      expect(workout.routine).to eql(routine)
245    end
246
247    it "prepares the correct number of sets" do
248      squat = create(:squat)
249      routine.add_exercise(squat, sets: 3)
250      workout = subject.next_workout_for(routine)
251      expect(workout.exercise_sets.length).to eql(3)
252    end
253  end
254
255  describe "#next_routine" do
256    include_context "stronglifts_program"
257    subject { create(:user) }
258
259    it "routines the next workout" do
260      create(:workout, routine: routine_a, user: subject)
261      expect(subject.next_routine).to eql(routine_b)
262    end
263
264    it "returns the first routine in the program" do
265      expect(subject.next_routine).to eql(routine_a)
266    end
267  end
268
269  describe "#last_workout" do
270    include_context "stronglifts_program"
271    subject { create(:user) }
272
273    it "returns the last workout" do
274      workout = create(:workout, user: subject, routine: routine_a)
275      expect(subject.last_workout).to eql(workout)
276    end
277
278    it "returns the last workout that included a specific exercise" do
279      deadlift_workout = create(:workout, user: subject, routine: routine_b)
280      deadlift_workout.train(deadlift, 315.lbs, repetitions: 5)
281      bench_workout = create(:workout, user: subject, routine: routine_a)
282      bench_workout.train(bench_press, 195.lbs, repetitions: 5)
283
284      expect(subject.last_workout(deadlift)).to eql(deadlift_workout)
285    end
286
287    it "returns nil when no workouts have been completed" do
288      expect(subject.last_workout).to be_nil
289    end
290
291    it "returns nil when the exercise has not been performed" do
292      bench_workout = create(:workout, user: subject, routine: routine_a)
293      bench_workout.train(bench_press, 195.lbs, repetitions: 5)
294
295      expect(subject.last_workout(deadlift)).to be_nil
296    end
297  end
298end