Giter Site home page Giter Site logo

andresmweber / mdlive-test Goto Github PK

View Code? Open in Web Editor NEW
1.0 2.0 0.0 1.61 MB

Coding Challenge from MDLive

JavaScript 100.00%
challenge test testing circleci unit-testing pagination express mongodb mongoose andres weber andresweber andresmweber code-challenge job-interview interview-test

mdlive-test's Introduction


MDLive QA Challenge
NodeJS logo MongoDB logo express logo jest logo circleci logo codeclimate logo

๐Ÿ“ Table of Contents

๐Ÿ“™ About

Process

  1. Started with express-generate and removed as much of the unnecessary scaffolding as I could.
  2. Implemented all necessary scripts in package.json to test, seed the db and deploy
  3. Added my own custom database connection, seed, and seed-helper functions to populate the database efficiently with the test data.
  4. Added the model for the app
  5. Added CircleCI and CodeClimate configurations to automate the testing of the project.
  6. Created the endpoint and set up the manual pagination.
  7. Added as many test cases as I could think of, some boundary tests and tested the examples provided in the instructions.
  8. Deployed to Heroku and set up a persistent MongoDB Database on Atlas

Notes

Pagination Implementation

From the challenge description it seemed that this implementation had a few unique characteristics:

  1. It had a nested query string, some options include a stringified Object form, bracket notated nested query params (e.g. range[by]) and a dot notated set of nested query params (e.g. range.by)
  2. The pagination could start based on finding matches for the start value, not just an index value.

For the first I chose to write my own query parameter parser that would create an object based on a given key prefix, for example ?range.by=id&range.start=5 would become {"range": {"by": "id", "start"=5}}

For the second I created a helper function searchArrayByProperty which attempted to find the matches given by the query string start/end parameters within the array.

Finally for the more traditional sorting I chose to use a switch statement which incorporated ascending and descending functions for both primitive data types we expected. This was so our sort/reverse could run in O(n log n) instead of adding another O(n) to the runtime complexity.

Query Parameter Structure

I chose to interpret the query as a nested query string in the form of ?key.subkey=value. This way I was able to parse the query parameters for the key and store all the subkey values in an object.

Another way of doing this would be to have the query parameter be called range and JSON.stringify an object with all the required key/value pairs then on the backend use JSON.parse. This would be easier on the backend but harder to type into the browser address bar, although it could be easier to send from the frontend as an object. I chose to have it easier to type in the browser address bar since it would be easier to quickly test manually.

Improvement Considerations

  • non-determinism: There is an inherent issue with using by=name&start=my-app-001: we are lucky that they match up directly with their inherent index, however if they had more unique names and the database was not static this would cause us to get different results per query. It also makes finding the next/previous pagination set harder since it's non trivial to determine the next start query's look up name if the names were unique and you did not want to parse the names as they are currently.
  • pagination: Based on the problem set and the aforementioned non-determinism it seems like it would be more effective to return an object with next/previous pagination parameters and possibly some type of trace back for the query itself.
  • mongoose queries: I assumed that due to the restriction of not being able to use a library to perform the pagination that we could not use mongoose to perform anything other than finding all of the model's documents and ignore any optimized database query methods we had available. If that were not the case, I would highly prefer to not query the entire set of model documents and instead pass the calculated pagination settings to native mongoose queries like Model.limit, Model.find, Model.skip, and Model.sort. The only native call that I used was Model.lean in order to speed up the overall query by roughly 4x since we are not using any of the mongoose Model functionality and that did not effect the pagination.

โš™๏ธ Setup

Installation

  • Clone the repo
  • Install the server dependencies with: npm install or yarn install
  • Install MongoDB to make sure you have the daemon running (or just connect to a MongoDB Cluster you created in the optional Environment step)
  • Seed the database by running yarn seed or npm run seed in the root directory
  • Run the local backend server using npm start or yarn start
  • Open http://localhost:3000 and Have fun!

Environment Variables

  • Set the following environment variables on | mac | windows | linux | or just create a .env file in the root directory
  • (optional) Create a Mongo DB Cluster to have a persistent hosted database
Environment Variables Description Default
PORT Port for the backend express server 3000
MONGODB_URI URI to log into mongodb mongodb://localhost/please-set-process-env-mongodb-uri
MONGODB_LOCAL override for localhost mongodb database name undefined

๐Ÿ“ก Endpoints

GET /apps

Returns the json list of apps matching the query params.

Example Queries
https://mdlive-test.herokuapp.com/apps
https://mdlive-test.herokuapp.com/apps?range.by=id
https://mdlive-test.herokuapp.com/apps?range.start=5&range.end=28&range.max=25
https://mdlive-test.herokuapp.com/apps?range.by=name&range.order=asc&range.start=my-app-150
https://mdlive-test.herokuapp.com/apps?range.by=name&range.order=desc&range.start=my-app-150&range.end=my-app-120
Query Parameters Type Default Description
range.by String "id" Only supports querying by "id" or "name".

NOTE: Must use String for range.start and range.end if specifying "name"

range.max Number 50 Maximum number of entries to return.
range.order String "asc" Sets Either 'asc' for ascending order or 'desc' for descending order.
range.start String or Integer 50 or "my-app-001" Identifier to match the start entry's range.by property
range.end String or Integer null Identifier to match the end entry's range.by property
Response Type
200 JSON

๐Ÿงช Testing

  • Run yarn test to run the test suite.
    • Note: You do not have to yarn seed in order to test the database but you DO have to have mongodb installed.
  • It will automatically connect to a local mongoose database named mdlive-test if you want to check out the database state after the test suite runs.

โ›๏ธ Built Using

โœ๏ธ Authors

mdlive-test's People

Contributors

andresmweber avatar

Stargazers

 avatar

Watchers

 avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.