My Lambda School Labs Experience

Christopher Girvin
6 min readMar 2, 2021

These last 4 weeks have been hectic. I’ve been working with a team of skilled individuals to create an app that makes education available to anyone on the planet, regardless of which kind of device they are on or their level of accessibility to the internet. It’s been amazing, but crazy hectic, at times. My sentiment of enthusiasm to be working with my team seems to be shared by all involved. At the beginning, I was afraid that either my team wouldn’t be there for me or be involved at all. I just thought this was going to be another project, where no one really did anything and I had to pick up the slack. Also, there’s always that fear of going into an unknown situation. I just didn’t know what to expect at all. I had heard both good and bad stories about how peoples labs went and was extremely excited when I initially met my teammates. I had known most of them prior to going in, so I knew I would be able to count on most of them right from the get-go. Overall… I enjoyed learning new technologies and learning some new techniques for coding efficiently from my teammates. It is definitely an experience I won’t soon forget.

Meeting with the Stakeholder

Our stakeholder was Frank Fusco, Product Manager at Lambda School. Lambda had an idea to create an open source Learning Management System that could be accessible to anyone in the world, regardless of the internet quality or device it was running on. This sounded like an amazing idea. I am all about open source software and learning being accessible to anyone, so I was completely hooked from the first meeting. Our meetings with Frank were absolutely key. Together with David Monson, the UI/UX Design Manager, and Ryan Hamblin as the Technical Engineering Manager, both of Lambda School, all of our stakeholder meetings resulted in clear direction and even all the support we needed to complete this project.

Challenges We Faced During our Build Process

One of the biggest challenges we struggled to overcome was the Unit Testing. We were very new to Unit Testing anyway, but we now had to figure out how to test our components while mocking the code that was need to render the component. We spent at least a day of just banging our heads against the wall and reading documentation. We reached out to everyone we knew that could possibly help with no positive results.

On day 2, continuing to bang our heads out of frustration, I took a break, went for a long walk and just thought about the problem at hand. The quote by Einstein came to me, as it does when I’m brainstorming, “Out of clutter, find simplicity.” So, when I came back from my walk I took another look at the code and realized that the component we were trying to test was just a function, and could be tested like any other simple function. No need to mock any authentication or local storage or any of the crazy complicated thoughts we had before. The final code for the unit testing for one of the reducers is below.

import expect from 'expect';
import {
userInitialState,
LOGIN_START,
LOGIN_SUCCESS,
LOGIN_FAIL,
LOGIN_RESOLVE,
UPDATE_USER_START,
UPDATE_USER_SUCCESS,
UPDATE_USER_FAIL,
UPDATE_USER_RESOLVE,
} from '../state/ducks/userDuck';

import { userReducer } from '../state/ducks';

describe("User Duck Testing", () => {
test("User reducer with mocked loginThunk test", () => {
// mock test data
const testUserid = 1;
const testUsername = 'testuser';
const testRoleName = 'testrole';
const testErrorMessage = 'this is a test login error message';
const testIdleStatus = 'idle';
const testPendingStatus = 'get/pending';
const testSuccessStatus = 'get/success';
const testErrorStatus = 'get/error';

// mock actions
const mockLoginStart = { type: LOGIN_START };
const mockLoginSuccess = { type: LOGIN_SUCCESS, payload: {userid: testUserid, username: testUsername, roles: [{ role: { name: testRoleName }}]}};
const mockLoginFailure = { type: LOGIN_FAIL, payload: testErrorMessage};
const mockLoginResolve = { type: LOGIN_RESOLVE };

// assertions
expect(userReducer(userInitialState, mockLoginStart).status).toEqual(testPendingStatus);
expect(userReducer(userInitialState, mockLoginSuccess).user.userid).toEqual(testUserid);
expect(userReducer(userInitialState, mockLoginSuccess).user.username).toEqual(testUsername);
expect(userReducer(userInitialState, mockLoginSuccess).status).toEqual(testSuccessStatus);
expect(userReducer(userInitialState, mockLoginSuccess).loggedIn).toBeTruthy();
expect(userReducer(userInitialState, mockLoginFailure).loggedIn).toBeFalsy();
expect(userReducer(userInitialState, mockLoginFailure).error).toEqual(testErrorMessage);
expect(userReducer(userInitialState, mockLoginFailure).status).toEqual(testErrorStatus);
expect(userReducer(userInitialState, mockLoginResolve).status).toEqual(testIdleStatus);
});

test("User reducer with mocked updateUserThunk test", () => {
// mock test data
const testUpdateUserid = 1;
const testUpdateUsername = 'newtestuser';
const testUpdateRoleName = 'newtestrole';
const testUpdateErrorMessage = 'this is a update fail error message';
const testUpdateIdleStatus = 'idle';
const testUpdatePendingStatus = 'edit/pending';
const testUpdateSuccessStatus = 'edit/success';
const testUpdateErrorStatus = 'edit/error';

// mock actions
const mockUpdateUserStart = { type: UPDATE_USER_START };
const mockUpdateUserSuccess = { type: UPDATE_USER_SUCCESS, payload: {userid: testUpdateUserid, username: testUpdateUsername, roles: [{ role: { name: testUpdateRoleName }},]}};
const mockUpdateUserFailure = { type: UPDATE_USER_FAIL, payload: testUpdateErrorMessage };
const mockUpdateUserResolve = { type: UPDATE_USER_RESOLVE };

// assertions
expect(userReducer(userInitialState, mockUpdateUserStart).status).toEqual(testUpdatePendingStatus);
expect(userReducer(userInitialState, mockUpdateUserSuccess).user.userid).toEqual(testUpdateUserid);
expect(userReducer(userInitialState, mockUpdateUserSuccess).user.username).toEqual(testUpdateUsername);
expect(userReducer(userInitialState, mockUpdateUserSuccess).status).toEqual(testUpdateSuccessStatus);
expect(userReducer(userInitialState, mockUpdateUserFailure).error).toEqual(testUpdateErrorMessage);
expect(userReducer(userInitialState, mockUpdateUserFailure).status).toEqual(testUpdateErrorStatus);
expect(userReducer(userInitialState, mockUpdateUserResolve).status).toEqual(testUpdateIdleStatus);
});
});

As is a typical outcome in life and in coding, simpler, not more complex, is usually the best way. But we finally overcame our problem as a team and we were stronger for it. Team work and communication were the real solutions to this problem, though. If I hadn’t had someone there with me to try everything else we could possibly think of, we would’ve never gotten to this resolution.

So, what was the final outcome?

Login Functionality

As you can see here, we have a login page that functions simply, all while being aesthetically simple and beautiful. Unfortunately, the ‘Register’ functionality is not yet implemented. Here, we are using Okta to authenticate users, which then communicates with our backend to see what role the have, Admin, Teacher, or Student. After your role is determined a dashboard is renders that allows or disallows you to execute certain actions. i.e. Admin can view/add/edit programs, courses, and modules, Teachers can view/add/edit courses and modules and view programs, and Students can view programs, courses, and modules.

Our Navigation Menu

This is our Admin’s Side Nav used for navigating throughout the site. It gives them the ability to revisit their Dashboard, create a program or course, visit a profile settings menu and edit their account, and logout.

Edit Program Functionality

Above is the Admin view of a program allowing them to click the edit icon and edit the current program, program’s courses, and course’s modules. As you can see, the user flow is very intuitive and the design follows our elegant design model we set out to achieve.

What is the future of this product?

The sky is the limit. The next team that picks up this product has a really good start, in my personal opinion. Some functionality that would need to be added would be, firstly, the ability for a user to actually sign up through the app, but it sounds like the instructors need to figure that one out first, so that one might not be a viable option since many problems we sought help from the instructor about were ultimately solved by one of our team members. If I were a betting man, I wouldn’t hold my breath on that one. Another would be for an Admin to have the ability to search for teachers, and maybe students, and add them to courses. Another would be for a teacher to be able to add assignments that can be graded and stored and a page where the student could view their current grade, as well as all of their graded assignments. This functionality could definitely be implemented in future releases.

Conclusion

To wrap it all up, we made it to our goal for the month and we very pleased where the final product ended up in a month’s time. As I stated before, I was just so happy to work with the team that I was placed in. We communicated well and everyone played a vital role in our final product, and I would be ecstatic if I were to work with this team again.

--

--