Skip to content

Convert UserAPI to Typescript #21

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 38 commits into
base: minoka-development
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
2959e53
added an interface for a Persona and declared the type of list as an …
kakizaki55 May 20, 2022
e9c46b5
added return types to methods.
kakizaki55 May 20, 2022
d3746c9
added return types for each method.
kakizaki55 May 20, 2022
93a21a8
added readonly to all types in Person interface
kakizaki55 May 20, 2022
5a25848
Merge branch 'minoka-development' into convert-to-typescript
kakizaki55 May 23, 2022
1511f4e
Merge branch 'minoka-development' into convert-to-typescript
kakizaki55 May 23, 2022
40db008
added Error as return types as well as empty [].
kakizaki55 May 23, 2022
7ac2bf4
getting rid of comment
kakizaki55 May 23, 2022
df2131e
getting rid of retunr type Error
kakizaki55 May 23, 2022
4eece1c
changed Arrays to ReadonlyArrays type. and had to change line 23 to s…
kakizaki55 May 23, 2022
15adc57
added UserFormMeta type for add user argument
kakizaki55 May 24, 2022
2c5f20e
Added UserFromMeta type for adding and updating user. added id parama…
kakizaki55 May 24, 2022
2555f78
typed the mock users as a Record obj, fixed addUser and getUsers to g…
kakizaki55 May 24, 2022
8b80772
changed mockUsers from function to just an object. made changes to ge…
kakizaki55 May 24, 2022
8515dc0
updated deleteUser by id for object model. test passing. still need t…
kakizaki55 May 24, 2022
2b3a210
searchByName function refactored for obj model
kakizaki55 May 24, 2022
e5a9614
refactrored getusers to use object.entires()
kakizaki55 May 24, 2022
22269f3
fixed update bu user Id and spaceing.
kakizaki55 May 24, 2022
193425d
opps forgot to push this one, made a utils file for the interfaces
kakizaki55 May 24, 2022
3725609
used the User interface instead of Record
kakizaki55 May 25, 2022
b46da91
getUserById refactored to user a map. still need to type .map
kakizaki55 May 25, 2022
e3cadca
Typed getUserById map invocation all variables seem to have types
kakizaki55 May 25, 2022
80a12be
refactored getUsers to user .map and typed
kakizaki55 May 25, 2022
021bbc7
worked with dustin, to use .map for getUsers spread op for update and…
kakizaki55 May 25, 2022
41b6b9f
test Written for gettig average age
kakizaki55 May 25, 2022
f8ef369
getAverageAge works but its kinda smelly. need to refactor
kakizaki55 May 25, 2022
4445b36
some refactoring, still needs work.
kakizaki55 May 25, 2022
89ee1c7
test written for geting all favorite colors.
kakizaki55 May 25, 2022
3cd001f
made two function getAllFavoriteColors, and getAllFavoriteColorBy Nam…
kakizaki55 May 26, 2022
f2a1ba7
refactored getAverageAge. refactored getAllColors to use a new Set() …
kakizaki55 May 26, 2022
35c5d6e
fixed minor typo
kakizaki55 May 26, 2022
a9fd28f
working but need to figure out typeing for useing bracket notation.
kakizaki55 May 26, 2022
7e29fab
getfavorite Color Count refactored.
kakizaki55 May 26, 2022
bc42318
getUserMeta method all done. test passing.
kakizaki55 May 26, 2022
3ce60b8
typed the retrun for getUserMeta
kakizaki55 May 26, 2022
b301823
spacing
kakizaki55 May 26, 2022
a7fd620
Merge pull request #24 from olioapps/user-stats-methods
kakizaki55 May 26, 2022
90c703c
Merge pull request #23 from olioapps/convert-to-Record
kakizaki55 May 26, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
91 changes: 74 additions & 17 deletions src/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,24 @@
import UserAPI from "./index"
import {
mockUsers,
mockUsers2,
userObject,
updatingUserObject,
updatingUserObjectError,
updatingUserObjectErrorWithId,
} from "./mockdata"

describe("Tests will go here!", () => {
beforeEach(() => {})

it("should make an instance of the UserAPI class and add a user, new user object should have an id.", () => {
const users = new UserAPI(mockUsers())
const users = new UserAPI(mockUsers)
const newUser = users.addUser(userObject)

expect(users.list).toHaveLength(5)
expect(users.getUsers()).toHaveLength(5)

expect(newUser).toEqual({ id: expect.any(String), ...userObject })
})

it("should show the correct error message, will fail if no errors are thrown", () => {
const users = new UserAPI(mockUsers())
const users = new UserAPI(mockUsers)

try {
expect(() => users.addUser({})).toThrow()
Expand All @@ -33,7 +31,7 @@ describe("Tests will go here!", () => {
})

it("should show the correct error message, will fail if no errors are thrown", () => {
const users = new UserAPI(mockUsers())
const users = new UserAPI(mockUsers)

try {
expect(() => users.addUser({})).toThrow()
Expand All @@ -43,7 +41,7 @@ describe("Tests will go here!", () => {
})

it("should get the correct user that matches their id", () => {
const users = new UserAPI(mockUsers())
const users = new UserAPI(mockUsers)
const targetUser1 = users.getUserById("1")
const targetUser2 = users.getUserById("3")

Expand All @@ -63,7 +61,7 @@ describe("Tests will go here!", () => {
})

it("should get a list of all the users, or an empty array other wise", () => {
const users = new UserAPI(mockUsers())
const users = new UserAPI(mockUsers)
const emptyusers = new UserAPI()

expect(users.getUsers()).toHaveLength(4)
Expand All @@ -72,8 +70,11 @@ describe("Tests will go here!", () => {
})

it("should update the users but return an error if user is not found or if the object doesn't have an id ", () => {
const users = new UserAPI(mockUsers())
const updatedUser = users.updateUserById(updatingUserObject)
const users = new UserAPI(mockUsers)
const validId = "0"
const noID = ""
const notValidId = "not a valid Id"
const updatedUser = users.updateUserById(validId, updatingUserObject)

expect(updatedUser).toEqual({
id: "0",
Expand All @@ -83,21 +84,21 @@ describe("Tests will go here!", () => {
})

try {
users.updateUserById(updatingUserObjectError)
users.updateUserById(noID, updatingUserObject)
} catch (err) {
expect(err.message).toEqual("We can not update a user without an id")
}

try {
users.updateUserById(updatingUserObjectErrorWithId)
users.updateUserById(notValidId, updatingUserObject)
} catch (err) {
expect(err.message).toEqual("There are no users found with that id.")
}
})

it("should be able to delete a user, and it should return the delete user.", () => {
const users = new UserAPI(mockUsers())
expect(users.list).toHaveLength(4)
const users = new UserAPI(mockUsers)
expect(users.getUsers()).toHaveLength(4)

const deletedUser = users.deleteUserById("3")

Expand All @@ -108,7 +109,7 @@ describe("Tests will go here!", () => {
name: "tim",
})

expect(users.list).toHaveLength(3)
expect(users.getUsers()).toHaveLength(3)

try {
users.deleteUserById("3")
Expand All @@ -118,7 +119,7 @@ describe("Tests will go here!", () => {
})

it("should return empty array or an array of users with any part of the their name matching the input argument.", () => {
const users = new UserAPI(mockUsers())
const users = new UserAPI(mockUsers)
const emptyArray = users.searchUserByName("not a real search")

expect(emptyArray).toEqual([])
Expand All @@ -135,4 +136,60 @@ describe("Tests will go here!", () => {

expect(thirdSearch).toHaveLength(2)
})
it("should return a number with the average age of all the users", () => {
const users = new UserAPI(mockUsers)

const averageAge = users.getAverageAge()

expect(averageAge).toEqual(30.5)

const users2 = new UserAPI(mockUsers2)

const averageAge2 = users2.getAverageAge()

expect(averageAge2).toEqual(31.666666666666668)
})

it("should get a array of all the favorite colors of all the users", () => {
const users = new UserAPI(mockUsers)
users.addUser(userObject)
users.addUser(userObject)
users.addUser(userObject)

const arrayOfFavoriteColors = users.getAllFavoriteColors()

expect(arrayOfFavoriteColors).toEqual(
new Set(["green", "black", "blue", "red"])
)
})

it("should get the favorite color count of each Color.", () => {
const users = new UserAPI(mockUsers)
users.addUser(userObject)
users.addUser(userObject)
users.addUser(userObject)
users.addUser({ name: "ted" })
users.addUser({ name: "ted" })
users.addUser({ name: "ted" })

const objectOfFavoriteColors = users.getFavoriteColorCount()
expect(objectOfFavoriteColors).toEqual({
green: 4,
blue: 1,
black: 1,
red: 1,
})
})
it("should return all user stats in an object", () => {
const users = new UserAPI(mockUsers)
users.addUser(userObject)
const userMeta = users.getUserMeta()

expect(userMeta).toEqual({
colorCount: { green: 2, black: 1, blue: 1, red: 1 },
allColors: new Set(["green", "black", "blue", "red"]),
averageAge: 30.6,
totalUsers: 5,
})
})
})
147 changes: 115 additions & 32 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,62 +1,145 @@
//@ts-nocheck
import { Person, UserFormMeta, Users } from "./interfaces"

export default class UserAPI {
constructor(users) {
this.list = users || []
list: Users

constructor(users: Users) {
this.list = users || {}
}
//random id generator
randomId = () => {

randomId = (): string => {
return Math.random().toString(24).slice(2)
}

addUser(user) {
addUser(user: UserFormMeta): Person {
if (!user.name) {
throw new Error("you need to at least have a name to add a user")
}
const newUser = { id: this.randomId(), ...user }
this.list.push(newUser)

const id = this.randomId()
const newUser = { id, ...user }
this.list = { ...this.list, [id]: newUser }
return newUser
}

getUserById(id) {
const targetUser = this.list.find(user => user.id === id)
getUserById(id: string): Person {
const targetUser = this.list[id]

if (!targetUser) {
throw new Error("There are no users found with that id.")
}

return targetUser
}

updateUserById(updatedUser) {
if (!updatedUser.id) {
updateUserById(id: string, updatedUser: Partial<UserFormMeta>): Person {
if (!id) {
throw new Error("We can not update a user without an id")
}
const updatedList = this.list.map(user => {
if (user.id === updatedUser.id) {
return { ...user, ...updatedUser }
}
return user
})
this.list = updatedList
return this.getUserById(updatedUser.id)
const foundUser = this.getUserById(id)

if (!foundUser) {
throw new Error("There are no users found with that id.")
}

const newUpdatedUser = { ...foundUser, ...updatedUser }
const updatedUserList = { ...this.list, [id]: newUpdatedUser }

this.list = updatedUserList
return newUpdatedUser
}

getUsers() {
return this.list
getUsers(): ReadonlyArray<Person> | [] {
const usersArray: ReadonlyArray<Person> = Object.values(this.list).map(
(value: Person) => {
return value
}
)

return usersArray
}

deleteUserById(id) {
const deletedUser = this.getUserById(id)
const newUsersList = this.list.filter(user => user.id !== id)
this.list = newUsersList
deleteUserById(id: string): Person {
if (!this.getUserById(id)) {
throw new Error("There are no users found with that id.")
}

const { [id]: deletedUser, ...rest } = this.list
this.list = rest

return deletedUser
}

searchUserByName(name) {
const filteredUserArray = this.list.filter(user => {
if (user.name.toLowerCase().includes(name.toLowerCase())) {
return user
}
})
searchUserByName(name: string): ReadonlyArray<Person> | [] {
const filteredUserArray: ReadonlyArray<Person> = Object.values(
this.list
).filter((value: Person) =>
value.name.toLowerCase().includes(name.toLowerCase())
)

return filteredUserArray
}

getAverageAge(): number {
const ageOnlyArray = Object.values(this.list).reduce(
(acc, person: Person) => {
if (person.age) {
return [...acc, person.age]
}
return acc
},
[] as number[]
)

const averageAge: number =
ageOnlyArray.reduce((prev: number, current: number) => prev + current) /
ageOnlyArray.length

return averageAge
}

getAllFavoriteColors() {
let onlyColors = new Set()

Object.values(this.list)
.filter((users: Person) => users.favoriteColor)
.map((users: Person) => {
onlyColors.add(users.favoriteColor)
})

return onlyColors
}

getFavoriteColorCount(): Record<string, number> {
const colorCount = Object.values(this.list).reduce(
(acc, person: Person) => {
if (acc[person?.favoriteColor as string]) {
const newColorCount = acc[person.favoriteColor as string] + 1

return {
...acc,
[person.favoriteColor as string]: newColorCount,
}
} else if (person.favoriteColor) {
return { ...acc, [person.favoriteColor]: 1 }
}

return acc
},
{} as Record<string, number>
)

return colorCount
}

getUserMeta(): Record<string, any> {
const userMeta = {
colorCount: this.getFavoriteColorCount(),
allColors: this.getAllFavoriteColors(),
averageAge: this.getAverageAge(),
totalUsers: Object.keys(this.list).length,
}

return userMeta
}
}
14 changes: 14 additions & 0 deletions src/interfaces.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
export interface Person {
readonly id: string
readonly name: string
readonly age?: number
readonly favoriteColor?: string
}

export type Users = Record<string, Person>

export interface UserFormMeta {
readonly name: string
readonly age?: number
readonly favoriteColor?: string
}
Loading