Skip to content
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

fixed issues with test environment #3

Merged
merged 1 commit into from
Jul 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
30 changes: 18 additions & 12 deletions .github/workflows/pipeline.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,12 @@ on:
- main

env:
COMMIT_MESSAGES: ${{ toJson(github.event.commits.*.message) }}
COMMIT: ${{ toJson(github.event.commits)[0] }}
COMMIT_MESSAGES: ${{ toJson(github.event.commits.*.message) }}
COMMIT: ${{ toJson(github.event.commits)[0] }}
SECRET: secrets.SECRET
MONGODB_URI: secrets.MONGODB_URI
TEST_MONGODB_URI: secrets.TEST_MONGODB_URI
DEV_MONGODB_URI: secrets.DEV_MONGODB_URI

jobs:
simple_deployment_pipeline:
Expand All @@ -25,12 +29,14 @@ jobs:
- run: npm run eslint && cd frontend && npm run eslint
- run: npm run build
- run: npm run test
- name: frontend tests
run: cd frontend && npm run test
- name: e2e tests
uses: cypress-io/github-action@v5
with:
command: cd frontend && npm run cypress
start: npm run start
wait-on: http://localhost:5000
command: cd frontend && npm run cypress
start: npm run start
wait-on: http://localhost:5000
- name: deployment
if: ${{ github.event_name == 'push' }}
run: curl https://api.render.com/deploy/srv-${{ secrets.RENDER_SERVICE_ID }}?key=${{ secrets.RENDER_API_KEY }}
Expand All @@ -54,10 +60,10 @@ jobs:
needs: [simple_deployment_pipeline]
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v4
- name: Bump version and push tag
if: ${{ github.event_name == 'push' && !contains(join(env.COMMIT_MESSAGES, ', '), '#skip')}}
uses: anothrNick/github-tag-action@8c8163ef62cf9c4677c8e800f36270af27930f42
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
DEFAULT_BUMP: patch
- uses: actions/checkout@v4
- name: Bump version and push tag
if: ${{ github.event_name == 'push' && !contains(join(env.COMMIT_MESSAGES, ', '), '#skip')}}
uses: anothrNick/github-tag-action@8c8163ef62cf9c4677c8e800f36270af27930f42
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
DEFAULT_BUMP: patch
6 changes: 3 additions & 3 deletions apitesting/blogs.rest → api_calls/blogs.rest
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
GET http://localhost:3001/api/blogs
GET http://localhost:3003/api/blogs

###
POST http://localhost:3001/api/blogs
POST http://localhost:3003/api/blogs
Content-Type : application/json
Authorization: bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InVzZXIxIiwiaWQiOiI2M2NhZmJjZmFlNTdmOWE1NGMxNGY2ZWUiLCJpYXQiOjE2NzQyNTQxODUsImV4cCI6MTY3NDI1Nzc4NX0.s_n4ZplhBS-lnbPUafmjEnedOtNDppi2CYxjpE1ZDxY

Expand All @@ -12,7 +12,7 @@ Authorization: bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InVzZ
"likes": 5
}
###
PUT http://localhost:3001/api/blogs/63c6ca1fb0152ad35a59b7c9
PUT http://localhost:3003/api/blogs/63c6ca1fb0152ad35a59b7c9
Content-Type: application/json

{
Expand Down
File renamed without changes.
File renamed without changes.
9 changes: 5 additions & 4 deletions app.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,13 @@ const app = express();
const loginRouter = require('./controllers/login');
const blogsRouter = require('./controllers/blogs');
const userRouter = require('./controllers/users');
const testingRouter = require('./controllers/testing');
const { tokenExtractor, errorHandler } = require('./utils/middleware');
const config = require('./utils/config');
const logger = require('./utils/logger');

mongoose.connect(config.MONGODB_URI)
mongoose
.connect(config.MONGODB_URI)
.then(() => {
logger.info('connected to MongoDB');
})
Expand All @@ -26,11 +28,10 @@ app.use('/api/blogs', blogsRouter);
app.use('/api/users', userRouter);
app.use(express.static('frontend/build'));

if(process.env.NODE_ENV === 'test') {
const testingRouter = require('./controllers/testing');
if (config.ENV === 'testing') {
app.use('/api/testing', testingRouter);
}

app.use(errorHandler);

module.exports = app;
module.exports = app;
28 changes: 27 additions & 1 deletion controllers/testing.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,38 @@
const router = require('express').Router();
const bcrypt = require('bcrypt');
const Blog = require('../models/blog');
const User = require('../models/user');
const { initialBlogs, initialUsers } = require('../tests/api/test_helper');

router.post('/reset', async (request, response) => {
await Blog.deleteMany({});
await User.deleteMany({});

await Promise.all(
initialUsers.map(async (user) => {
const newUser = new User({
username: user.username,
name: user.name,
password: await bcrypt.hash(user.password, 10),
});
return await newUser.save();
})
);

const someUser = await User.findOne({ username: 'user1' });

const savedBlogs = await Promise.all(
initialBlogs.map((blog) => {
const newBlog = Blog(blog);
newBlog.user = someUser._id;
return newBlog.save();
})
);

someUser.blogs = savedBlogs.map((blog) => blog._id);
await someUser.save();

response.status(204).end();
});

module.exports = router;
module.exports = router;
8 changes: 8 additions & 0 deletions jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
const config = {
testPathIgnorePatterns: ['frontend/*'],
verbose: true,
forceExit: true,
testEnvironment: 'node',
};

module.exports = config;
67 changes: 32 additions & 35 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,37 +1,34 @@
{
"name": "bloglist",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"start": "NODE_ENV=production node index.js",
"dev": "NODE_ENV=development nodemon index.js",
"build": "cd frontend && npm run build",
"render:deploy": "npm install && cd frontend && npm install && npm run build",
"eslint": "eslint .",
"test": "NODE_ENV=test jest --verbose --runInBand --forceExit",
"start:test": "NODE_ENV=test node index.js"
},
"author": "",
"license": "ISC",
"dependencies": {
"bcrypt": "^5.1.0",
"cors": "^2.8.5",
"dotenv": "^16.0.3",
"express": "^4.18.2",
"express-async-errors": "^3.1.1",
"jsonwebtoken": "^9.0.0",
"mongoose": "^6.8.3"
},
"devDependencies": {
"eslint": "^8.32.0",
"eslint-plugin-cypress": "^3.3.0",
"eslint-plugin-react": "^7.34.3",
"jest": "^29.3.1",
"nodemon": "^2.0.20",
"supertest": "^6.3.3"
},
"jest": {
"testEnvironment": "node"
}
"name": "bloglist",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"start": "NODE_ENV=production node index.js",
"dev": "NODE_ENV=development nodemon index.js",
"build": "cd frontend && npm run build",
"render:deploy": "npm install && cd frontend && npm install && npm run build",
"eslint": "eslint .",
"test": "NODE_ENV=testing jest --verbose --runInBand --forceExit",
"start:test": "NODE_ENV=testing node index.js"
},
"author": "",
"license": "ISC",
"dependencies": {
"bcrypt": "^5.1.0",
"cors": "^2.8.5",
"dotenv": "^16.0.3",
"express": "^4.18.2",
"express-async-errors": "^3.1.1",
"jsonwebtoken": "^9.0.0",
"mongoose": "^6.8.3"
},
"devDependencies": {
"eslint": "^8.32.0",
"eslint-plugin-cypress": "^3.3.0",
"eslint-plugin-react": "^7.34.3",
"jest": "^29.3.1",
"nodemon": "^2.0.20",
"supertest": "^6.3.3"
}
}
76 changes: 28 additions & 48 deletions tests/api/blogs.test.js
Original file line number Diff line number Diff line change
@@ -1,43 +1,21 @@
const mongoose = require('mongoose');
const bcrypt = require('bcrypt');
const app = require('../../app');
const supertest = require('supertest');
const { initialBlogs, blogsInDb, invalidId } = require('./test_helper');

const api = supertest(app);
const Blog = require('../../models/blog');
const User = require('../../models/user');
const { initialBlogs, initialUsers, blogsInDb, invalidId } = require('./test_helper');

const getToken = async () => {
const token = (await api
.post('/api/login')
.send({ username: 'user1', password: 'salasana' }))
.body.token;
const token = (
await api
.post('/api/login')
.send({ username: 'user1', password: 'salasana' })
).body.token;
return token;
};

beforeEach(async () => {
await Blog.deleteMany({});
await User.deleteMany({});

await Promise.all(initialUsers.map(async user => {
const newUser = new User({
username: user.username,
name: user.name,
password: await bcrypt.hash(user.password, 10)
});
return await newUser.save();
}));

const someUser = await User.findOne({ username: 'user1' });

const savedBlogs = await Promise.all(initialBlogs.map(blog => {
const newBlog = Blog(blog);
newBlog.user = someUser._id;
return newBlog.save();
}));

someUser.blogs = savedBlogs.map(blog => blog._id);
await someUser.save();
await api.post('/api/testing/reset');
});

describe('GET api/blogs', () => {
Expand Down Expand Up @@ -69,13 +47,13 @@ describe('POST api/blogs', () => {
title: 'uusiblogi',
author: 'kirjoittaja',
url: 'osoite',
likes: 1
likes: 1,
};

test('response has status 400 when title or url is missing', async () => {
const token = await getToken();

const blogWithMissingProps = { ... newBlog };
const blogWithMissingProps = { ...newBlog };
delete blogWithMissingProps.title, blogWithMissingProps.url;

await api
Expand All @@ -98,15 +76,21 @@ describe('POST api/blogs', () => {

test('saves blog with user property', async () => {
const token = await getToken();
const response = await api.post('/api/blogs').set('authorization', `Bearer ${token}`).send(newBlog);
const response = await api
.post('/api/blogs')
.set('authorization', `Bearer ${token}`)
.send(newBlog);
expect(response.body.user).toBeDefined();
});

test('gives property "likes" a default value of 0', async () => {
const token = await getToken();
const blogWith0Likes = { ... newBlog };
const blogWith0Likes = { ...newBlog };
delete blogWith0Likes.likes;
const response = await api.post('/api/blogs').set('authorization', `Bearer ${token}`).send(blogWith0Likes);
const response = await api
.post('/api/blogs')
.set('authorization', `Bearer ${token}`)
.send(blogWith0Likes);
expect(response.body.likes).toBe(0);
});
});
Expand Down Expand Up @@ -143,16 +127,15 @@ describe('DELETE api/blogs/id', () => {

test('returns status code 401 on missing token', async () => {
const toDelete = (await blogsInDb())[0].id;
await api
.delete(`/api/blogs/${toDelete}`)
.expect(401);
await api.delete(`/api/blogs/${toDelete}`).expect(401);
});

test('returns status code 401 if user is not authorized to delete the blog', async () => {
const wrongUserToken = (await api
.post('/')
.send({ username: 'user2', password: 'salasana' }))
.body.token;
const wrongUserToken = (
await api
.post('/')
.send({ username: 'user2', password: 'salasana' })
).body.token;
const toDelete = (await blogsInDb())[0].id;
await api
.delete(`/api/blogs/${toDelete}`)
Expand All @@ -170,15 +153,12 @@ describe('PUT api/blogs/id', () => {
expect(response.body.likes).toBe(10);
});

test('returns 200 on succesfull update', async () => {
test('returns 200 on successful update', async () => {
const toUpdate = (await blogsInDb())[0].id;
await api
.put(`/api/blogs/${toUpdate}`)
.send({ likes: 10 })
.expect(200);
await api.put(`/api/blogs/${toUpdate}`).send({ likes: 10 }).expect(200);
});
});

afterAll(() => {
mongoose.connection.close();
});
});
Loading