Skip to content

Commit

Permalink
feat: mock example in javascript using prisma (#7264)
Browse files Browse the repository at this point in the history
* feat: mock example in javascript using prisma

* Add test file

---------

Co-authored-by: Jon Harrell <4829245+jharrell@users.noreply.github.com>
  • Loading branch information
ludralph and jharrell authored Dec 20, 2024
1 parent b53fad0 commit edcf902
Show file tree
Hide file tree
Showing 10 changed files with 284 additions and 0 deletions.
8 changes: 8 additions & 0 deletions .github/tests/orm/prisma-mocking-javascript/run.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#!/bin/sh

set -eu

npm install
npx prisma generate

npm run test
2 changes: 2 additions & 0 deletions orm/prisma-mocking-javascript/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
node_modules/
coverage/
41 changes: 41 additions & 0 deletions orm/prisma-mocking-javascript/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
## A simple mock example using Prisma in Javascript

## Installation

1. Install dependencies:
```
npm install
```

2. Ensure Prisma is properly configured in your project. Set up your Prisma schema file and database connection.

Run Prisma commands to generate the client:
```
npx prisma generate
```

## Testing

Unit tests are provided to validate the functionality of the utility functions. Mocking is used for Prisma client interactions.


To run the tests:
```
npm test
```

## Test Coverage

- The tests cover the following scenarios:

- Creating a user with valid data.

- Handling errors when terms are not accepted.

- Updating user information.

- Retrieving all users.

- Transactional queries for posts and post count.

- Fetching posts by a specific user.
107 changes: 107 additions & 0 deletions orm/prisma-mocking-javascript/__test__/with-singleton.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
const { createUser, updateUsername, getAllUsers, getUsersAndCount, getPostsByUser } = require('../functions-without-context')
const { prismaMock } = require('../singleton')

test('should create new user ', async () => {
const user = {
id: 1,
name: 'Rich',
email: 'hello@prisma.io',
acceptTermsAndConditions: true,
}

prismaMock.user.create.mockResolvedValue(user)

await expect(createUser(user)).resolves.toEqual({
id: 1,
name: 'Rich',
email: 'hello@prisma.io',
acceptTermsAndConditions: true,
})
})

test('should update a users name ', async () => {
const user = {
id: 1,
name: 'Rich Haines',
email: 'hello@prisma.io',
acceptTermsAndConditions: true,
}

prismaMock.user.update.mockResolvedValue(user)

await expect(updateUsername(user)).resolves.toEqual({
id: 1,
name: 'Rich Haines',
email: 'hello@prisma.io',
acceptTermsAndConditions: true,
})
})

test('should fail if user does not accept terms', async () => {
const user = {
id: 1,
name: 'Rich Haines',
email: 'hello@prisma.io',
acceptTermsAndConditions: false,
}

prismaMock.user.create.mockImplementation()

await expect(createUser(user)).resolves.toEqual(
new Error('User must accept terms!')
)
})

test('should retrieve all the users from the database', async () => {

const dummyUsers = [
{
firstName: "John",
lastName: "Doe",
email: "johnDoe@gmail.com",
paidUser: false
}
]

prismaMock.user.findMany.mockResolvedValue(dummyUsers)
await expect(getAllUsers()).resolves.toEqual(dummyUsers)

})

test('mocks sequential Prisma operation inside a transaction', async () => {
// Mocked data
const mockedPostsData = [{ id: 1, title: 'Post with prisma' }];
const mockedCount = 1;

prismaMock.$transaction.mockResolvedValueOnce([
mockedPostsData, // Mocking the first operation
mockedCount // Mocking the second operation
]);

// Invoke the function
const result = await getUsersAndCount();


// Assertions to validate the result
expect(result.posts).toEqual(mockedPostsData);
expect(result.totalPosts).toEqual(mockedCount);
});

test('should return all posts by a specific user', async () => {
const email = 'alice@prisma.io';

const posts = [
{ id: 1, title: 'First Post', content: 'Content of the first post' },
{ id: 2, title: 'Second Post', content: 'Content of the second post' },
];


prismaMock.user.findUniqueOrThrow.mockReturnValue({
posts: jest.fn().mockResolvedValue(posts),
});

const result = await getPostsByUser(email);

expect(result).toEqual(posts);
});

7 changes: 7 additions & 0 deletions orm/prisma-mocking-javascript/client.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
const { PrismaClient } = require('@prisma/client')

const prisma = new PrismaClient()

module.exports = {
prisma
}
57 changes: 57 additions & 0 deletions orm/prisma-mocking-javascript/functions-without-context.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
const { prisma } = require("./client")

async function createUser(user) {
if (user.acceptTermsAndConditions) {
return await prisma.user.create({
data: user
})
} else {
return new Error("User must accept terms!")
}
}

async function updateUsername(user) {
return await prisma.user.update({
where: { id: user.id },
data: user
})
}

async function getAllUsers() {
return new Promise(async (resolve, reject) => {
prisma.user
.findMany()
.then((users) => {
resolve(users)
})
.catch((error) => {
reject({ error: 'Could not fetch users' })
});
});
}

async function getUsersAndCount() {
const [posts, totalPosts] = await prisma.$transaction([
prisma.posts.findMany(),
prisma.post.count(),
]);


return { posts, totalPosts };
}

async function getPostsByUser(email) {
const posts = await prisma.user
.findUniqueOrThrow({ where: { email } })
.posts()

return posts;
}

module.exports = {
createUser,
updateUsername,
getAllUsers,
getUsersAndCount,
getPostsByUser
}
5 changes: 5 additions & 0 deletions orm/prisma-mocking-javascript/jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
module.exports = {
clearMocks: true,
testEnvironment: 'node',
setupFilesAfterEnv: ['<rootDir>/singleton.js'],
}
16 changes: 16 additions & 0 deletions orm/prisma-mocking-javascript/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"name": "script",
"version": "1.0.0",
"license": "MIT",
"scripts": {
"test": "jest",
"dev": "node ./script.js"
},
"dependencies": {
"@prisma/client": "^6.1.0"
},
"devDependencies": {
"jest-mock-extended": "^2.0.4",
"prisma": "^6.1.0"
}
}
24 changes: 24 additions & 0 deletions orm/prisma-mocking-javascript/prisma/schema.prisma
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
generator client {
provider = "prisma-client-js"
}

datasource db {
provider = "sqlite"
url = "file:./dev.db"
}

model User {
id Int @id @default(autoincrement())
email String @unique
name String?
posts Post[]
acceptTermsAndConditions Boolean
}

model Post {
id Int @id @default(autoincrement())
title String
content String
author User @relation(fields: [authorId], references: [id])
authorId Int
}
17 changes: 17 additions & 0 deletions orm/prisma-mocking-javascript/singleton.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
const { mockDeep, mockReset } = require("jest-mock-extended")

const { prisma } = require("./client")

jest.mock("./client", () => ({
prisma: mockDeep()
}))

beforeEach(() => {
mockReset(prismaMock)
})

const prismaMock = prisma

module.exports = {
prismaMock
}

0 comments on commit edcf902

Please sign in to comment.