Skip to content

Commit f5b8f94

Browse files
committed
(project init)
1 parent afa1a1b commit f5b8f94

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

60 files changed

+6501
-175
lines changed

README.md

Lines changed: 13 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,13 @@
1-
This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app).
2-
3-
## Getting Started
4-
5-
First, run the development server:
6-
7-
```bash
8-
npm run dev
9-
# or
10-
yarn dev
11-
```
12-
13-
Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
14-
15-
You can start editing the page by modifying `pages/index.tsx`. The page auto-updates as you edit the file.
16-
17-
[API routes](https://nextjs.org/docs/api-routes/introduction) can be accessed on [http://localhost:3000/api/hello](http://localhost:3000/api/hello). This endpoint can be edited in `pages/api/hello.ts`.
18-
19-
The `pages/api` directory is mapped to `/api/*`. Files in this directory are treated as [API routes](https://nextjs.org/docs/api-routes/introduction) instead of React pages.
20-
21-
## Learn More
22-
23-
To learn more about Next.js, take a look at the following resources:
24-
25-
- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
26-
- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.
27-
28-
You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome!
29-
30-
## Deploy on Vercel
31-
32-
The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.
33-
34-
Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details.
1+
# Deers.IO
2+
3+
## Dependencies
4+
- Postgres
5+
- Redis
6+
7+
## Env Vars
8+
- `DATABASE_URL`
9+
- `MINIO_ACCESS_KEY`
10+
- `MINIO_SECRET_KEY`
11+
- `MINIO_HOST`
12+
- `MINIO_PORT`
13+
- `REDIS_HOST`

__test__/assets/white.png

351 Bytes
Loading

__test__/assets/white_1024.png

837 Bytes
Loading

__test__/assets/white_big.png

595 KB
Loading

controllers/__tests__/commission.test.ts

Lines changed: 379 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 238 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,238 @@
1+
import prisma from '../../util/prisma';
2+
import { makeError } from '../../util/error';
3+
import { createEntity, deleteEntity, getEntities, getEntity, updateEntity } from '../entity';
4+
import { PrismaClientKnownRequestError } from '@prisma/client/runtime';
5+
6+
7+
describe('entity controller', () => {
8+
beforeEach(() => {
9+
jest.mock('../../util/prisma');
10+
})
11+
12+
afterEach(() => {
13+
jest.restoreAllMocks();
14+
});
15+
16+
describe('create entity', () => {
17+
test('valid create - no socials', () => {
18+
const spy = jest.spyOn(prisma.entity, 'create');
19+
spy.mockResolvedValueOnce({ id: 1, type: 'ARTIST', name: 'testArtist' });
20+
21+
expect.assertions(1)
22+
return expect(createEntity({ name: 'testArtist', type: 'ARTIST' })).resolves.toEqual({id: 1, type: 'ARTIST', name: 'testArtist'});
23+
})
24+
25+
test('valid create - with socials', () => {
26+
const spy = jest.spyOn(prisma.entity, 'create');
27+
spy.mockResolvedValueOnce({ id: 1, type: 'ARTIST', name: 'testArtist', });
28+
29+
expect.assertions(1)
30+
return expect(
31+
createEntity({
32+
name: 'testArtist',
33+
type: 'ARTIST',
34+
socials: [
35+
{ type: 'TELEGRAM', value: 'telegramArtist' },
36+
{ type: 'TWITTER', value: 'twitterArtist' },
37+
{ type: 'WEBSITE', value: 'https://websiteArtist.com' },
38+
{ type: 'FURAFFINITY', value: 'furaffinityArtist' },
39+
{ type: 'CUSTOM', value: 'customArtistValue', name: 'customField' },
40+
]
41+
})
42+
).resolves.toEqual({id: 1, type: 'ARTIST', name: 'testArtist'});
43+
})
44+
45+
test('invalid entity type', () => {
46+
expect.assertions(1)
47+
return expect(createEntity({ name: 'testArtist', type: 'wrong type' })).rejects.toEqual(makeError('user', 'Invalid entity type'));
48+
})
49+
50+
test('invalid social type', () => {
51+
expect.assertions(1)
52+
return expect(createEntity({ name: 'testCharacter', type: 'CHARACTER', socials: [{type: "wrong type", value: "something"}] }))
53+
.rejects.toEqual(makeError('user', 'Invalid social. Non-valid type provided'));
54+
})
55+
56+
test('invalid social form', () => {
57+
expect.assertions(1)
58+
return expect(createEntity({ name: 'testCharacter', type: 'CHARACTER', socials: [{type: "wrong type"}] }))
59+
.rejects.toEqual(makeError('user', 'Invalid social. Must provide type, value'));
60+
})
61+
62+
test('non-custom social provided name', () => {
63+
expect.assertions(1)
64+
return expect(createEntity({ name: 'testCharacter', type: 'CHARACTER', socials: [{type: 'TELEGRAM', name: "bad", value: "something"}] }))
65+
.rejects.toEqual(makeError('user', 'Invalid social. Non-custom social fields should not specify name'));
66+
})
67+
68+
test('custom social missing name', () => {
69+
expect.assertions(1)
70+
return expect(createEntity({ name: 'testCharacter', type: 'CHARACTER', socials: [{type: "CUSTOM", value: "something"}] }))
71+
.rejects.toEqual(makeError('user', 'Invalid social. Custom socials must specify name'));
72+
})
73+
74+
test('prisma error', () => {
75+
const spy = jest.spyOn(prisma.entity, 'create');
76+
spy.mockRejectedValueOnce(new Error());
77+
expect.assertions(1)
78+
return expect(createEntity({ name: 'testCharacter', type: 'CHARACTER', socials: [{type: "CUSTOM", name: 'test', value: "something"}] }))
79+
.rejects.toEqual(makeError('server'));
80+
})
81+
})
82+
83+
describe('get entity', () => {
84+
test('valid fetch', () => {
85+
const spy = jest.spyOn(prisma.entity, 'findUnique');
86+
87+
const mock_entity = {
88+
id: 1,
89+
name: "testArtist",
90+
type: 'ARTIST',
91+
socials: [ { id: 1, type: "TELEGRAM", value: 'telegramArtist', name: null, entityId: 1 } ]
92+
}
93+
// @ts-ignore
94+
spy.mockResolvedValueOnce(mock_entity);
95+
96+
expect.assertions(1)
97+
return expect(getEntity(1)).resolves.toEqual(mock_entity);
98+
})
99+
100+
test('non-existant entity', () => {
101+
const spy = jest.spyOn(prisma.entity, 'findUnique');
102+
spy.mockRejectedValueOnce(new PrismaClientKnownRequestError('', 'P2001', ''));
103+
104+
expect.assertions(1);
105+
return expect(getEntity(1)).rejects.toEqual(makeError('user', 'Could not find entity'));
106+
})
107+
108+
test('prisma error', () => {
109+
const spy = jest.spyOn(prisma.entity, 'findUnique');
110+
spy.mockRejectedValueOnce(new Error());
111+
112+
expect.assertions(1);
113+
return expect(getEntity(1)).rejects.toEqual(makeError('server'));
114+
})
115+
116+
test('invalid ID', () => {
117+
expect.assertions(1);
118+
return expect(getEntity(NaN)).rejects.toEqual(makeError('user', 'Invalid ID provided'))
119+
})
120+
})
121+
122+
describe('get entities', () => {
123+
test('valid fetch', () => {
124+
const spy = jest.spyOn(prisma.entity, 'findMany');
125+
spy.mockResolvedValueOnce([1,2].map(i => ({id: i, name: 'testEnt', type: 'ARTIST'})));
126+
127+
expect.assertions(1);
128+
return expect(getEntities()).resolves.toEqual([1,2].map(i => ({id: i, name: 'testEnt', type: 'ARTIST'})));
129+
})
130+
131+
test('prisma error', () => {
132+
const spy = jest.spyOn(prisma.entity, 'findMany');
133+
spy.mockRejectedValueOnce(new Error());
134+
135+
expect.assertions(1)
136+
return expect(getEntities()).rejects.toEqual(makeError('server'));
137+
})
138+
})
139+
140+
describe('delete entity', () => {
141+
test('valid deletion', () => {
142+
const spy = jest.spyOn(prisma.entity, 'delete');
143+
spy.mockResolvedValueOnce({id: 1, name: 'testEnt', type: 'ARTIST'});
144+
expect.assertions(1)
145+
return expect(deleteEntity(1)).resolves.toEqual({id: 1, name: 'testEnt', type: 'ARTIST'});
146+
})
147+
148+
test('invalid ID', () => {
149+
expect.assertions(1)
150+
return expect(deleteEntity(NaN)).rejects.toEqual(makeError('user', 'Invalid ID provided'));
151+
})
152+
153+
test('non-existant entity', () => {
154+
const spy = jest.spyOn(prisma.entity, 'delete');
155+
spy.mockRejectedValueOnce(new PrismaClientKnownRequestError('', 'P2001', ''));
156+
expect.assertions(1);
157+
return expect(deleteEntity(1)).rejects.toEqual(makeError('user', 'Could not find entity'));
158+
})
159+
160+
test('entity has associated commissions', () => {
161+
const spy = jest.spyOn(prisma.entity, 'delete');
162+
spy.mockRejectedValueOnce(new PrismaClientKnownRequestError('', 'P2003', ''));
163+
expect.assertions(1);
164+
return expect(deleteEntity(1)).rejects.toEqual(makeError('user', 'Entity has commissions associated with it'));
165+
})
166+
167+
test('prisma error', () => {
168+
const spy = jest.spyOn(prisma.entity, 'delete');
169+
spy.mockRejectedValueOnce(new Error());
170+
expect.assertions(1);
171+
return expect(deleteEntity(1)).rejects.toEqual(makeError('server'));
172+
})
173+
})
174+
175+
describe('update entity', () => {
176+
test('valid update', () => {
177+
const spy = jest.spyOn(prisma.entity, 'update');
178+
spy.mockResolvedValueOnce({id: 1, name: 'newName', type: 'CHARACTER'});
179+
expect.assertions(1);
180+
const updateArgs = {
181+
name: 'newName',
182+
type: 'CHARACTER',
183+
socials: {
184+
add: [{type: 'TELEGRAM', value: 'entTelegram'}],
185+
remove: [1,2,3]
186+
}
187+
}
188+
return expect(updateEntity(1, updateArgs)).resolves.toEqual({id: 1, name: 'newName', type: 'CHARACTER'});
189+
})
190+
191+
test('invalid name', () => {
192+
expect.assertions(1)
193+
return expect(updateEntity(1, {name: ''})).rejects.toEqual(makeError('user', 'Entity name cannot be empty'));
194+
})
195+
196+
test('invalid type', () => {
197+
expect.assertions(1)
198+
return expect(updateEntity(1, {type: ''})).rejects.toEqual(makeError('user', 'Invalid entity type'));
199+
})
200+
201+
test('invalid social type', () => {
202+
expect.assertions(1)
203+
return expect(updateEntity(1, {socials: { add: [{type: "wrong type", value: "wrong"}] }})).rejects.toEqual(makeError('user', 'Invalid social. Non-valid type provided'));
204+
})
205+
206+
test('invalid social form', () => {
207+
expect.assertions(1)
208+
return expect(updateEntity(1, {socials: { add: [{type: "wrong type"}] }})).rejects.toEqual(makeError('user', 'Invalid social. Must provide type, value'));
209+
})
210+
211+
test('non-custom social with name', () => {
212+
expect.assertions(1)
213+
return expect(updateEntity(1, {socials: { add: [{type: "TELEGRAM", value: 'entTelegram', name: 'bad'}] }})).rejects.toEqual(makeError('user', 'Invalid social. Non-custom social fields should not specify name'));
214+
})
215+
216+
test('custom social without name', () => {
217+
expect.assertions(1)
218+
return expect(updateEntity(1, {socials: { add: [{type: "CUSTOM", value: 'entVal'}] }})).rejects.toEqual(makeError('user', 'Invalid social. Custom socials must specify name'));
219+
})
220+
221+
test('invalid social ID', () => {
222+
expect.assertions(1)
223+
return expect(updateEntity(1, {socials: { remove: [NaN] }})).rejects.toEqual(makeError('user', 'Invalid ID provided'));
224+
})
225+
226+
test('invalid entity ID', () => {
227+
expect.assertions(1)
228+
return expect(updateEntity(NaN, {socials: { remove: [NaN] }})).rejects.toEqual(makeError('user', 'Invalid ID provided'));
229+
})
230+
231+
test('prisma error', () => {
232+
const spy = jest.spyOn(prisma.entity, 'update');
233+
spy.mockRejectedValueOnce(new Error());
234+
expect.assertions(1);
235+
return expect(updateEntity(1, {name: "something"})).rejects.toEqual(makeError('server'));
236+
})
237+
})
238+
})

controllers/__tests__/user.test.ts

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import { createUser, validateCredentials } from '../user';
2+
import prisma from '../../util/prisma';
3+
import { makeError } from '../../util/error';
4+
5+
6+
describe('user controller', () => {
7+
beforeEach(() => {
8+
jest.mock('../../util/prisma');
9+
})
10+
11+
afterEach(() => {
12+
jest.restoreAllMocks();
13+
});
14+
15+
const mock_user = {
16+
username: 'testuser',
17+
password: 'testpass',
18+
};
19+
20+
const mock_user_hashed = {
21+
username: 'testuser',
22+
password: '$2b$08$S5YDuYLmC3uuM5zpkpxtsuklUm9X9EynvEoR7osWcXppZ0Hjclfrm',
23+
}
24+
25+
test('successfully creates user', async () => {
26+
const prismaSpy = jest.spyOn(prisma.user, 'create');
27+
prismaSpy.mockResolvedValueOnce({...mock_user, id: 1});
28+
await createUser(mock_user.username, mock_user.password);
29+
30+
expect(prismaSpy).toHaveBeenCalledTimes(1);
31+
const args = prismaSpy.mock.lastCall![0].data;
32+
expect(args.username).toBe(mock_user.username);
33+
expect(args.password).not.toBe(mock_user.password);
34+
});
35+
36+
test('prisma fails on create user', () => {
37+
const prismaSpy = jest.spyOn(prisma.user, 'create');
38+
prismaSpy.mockRejectedValueOnce(new Error());
39+
expect.assertions(1);
40+
41+
return expect(createUser(mock_user.username, mock_user.password)).rejects.toEqual(makeError('server'))
42+
});
43+
44+
test('successfully validates password', async () => {
45+
const prismaSpy = jest.spyOn(prisma.user, 'findUnique');
46+
prismaSpy.mockResolvedValueOnce({ id: 1, username: mock_user.username, password: mock_user_hashed.password})
47+
48+
const result = await validateCredentials(mock_user.username, mock_user.password);
49+
expect(result).toBeTruthy();
50+
})
51+
52+
test('validation could not find user', () => {
53+
const prismaSpy = jest.spyOn(prisma.user, 'findUnique');
54+
prismaSpy.mockRejectedValueOnce(new Error());
55+
expect.assertions(1);
56+
57+
return expect(validateCredentials(mock_user.username, mock_user.password)).rejects.toEqual(makeError('server'))
58+
})
59+
})

0 commit comments

Comments
 (0)