Skip to content
Open
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
9 changes: 9 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,15 @@ language: node_js
node_js:
- "12"

services:
- mongodb

before_script:
- mongo test_collection --eval 'db.createUser({user:"test",pwd:"test",roles:["readWrite"]});'

env:
- CONNECTION=mongodb://test:test@localhost:27017/test_collection

install:
- npm install

Expand Down
14 changes: 13 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,15 @@
## CI example [![Build Status](https://travis-ci.com/geekbrains-web/example-travis-ci.svg?branch=master)](https://travis-ci.com/geekbrains-web/example-travis-ci)
# CI example [![Build Status](https://travis-ci.com/geekbrains-web/example-travis-ci.svg?branch=master)](https://travis-ci.com/geekbrains-web/example-travis-ci)

Пример непрерывной интеграции (CI) приложения на Node.js используя Travis CI

Демонстрация процесса сборки: [Job log](https://travis-ci.com/geekbrains-web/example-travis-ci)

## Краткое описание настройки
Для начала нам нужно зарегестрироваться на сервисе [Travis CI](https://travis-ci.com) и дать доступ приложению к своим репозиториям/репозиторию в интерфейсе GitHub.

После этого, необходимо настроить выбранный репозиторий – создать в нем файл `.travis.yml` с необходимыми настройками. Подробно изучить настройки можно в [официальной документации](https://docs.travis-ci.com).

## Продвинутые возможности
Есть возможность запустить базы данных и протестировать ваше приложение вместе с ними. Пример работы с MongoDB вы можете увидеть в [Pull request #1](https://github.com/geekbrains-web/example-travis-ci/pull/1). Более подробно и интеграции с другими сервисами указаны в [документации](https://docs.travis-ci.com/user/database-setup/)

Кроме того, есть возможность настроить deployment на сервер, например, только когда вы вносите изменения в ветку мастер. Более подробно в [документации](https://docs.travis-ci.com/user/deployment/)
3 changes: 3 additions & 0 deletions jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module.exports = {
testEnvironment: "node"
};
4 changes: 4 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,5 +26,9 @@
"eslint-plugin-promise": "^4.2.1",
"eslint-plugin-standard": "^4.0.0",
"jest": "^24.8.0"
},
"dependencies": {
"bcrypt": "^3.0.6",
"mongoose": "^5.6.5"
}
}
3 changes: 3 additions & 0 deletions src/mongoClient.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
const mongoose = require("mongoose");

module.exports = mongoose.connect(process.env.CONNECTION, {useNewUrlParser: true});
24 changes: 24 additions & 0 deletions src/userModel.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
const mongoose = require("mongoose");
const bcrypt = require("bcrypt");

const UserSchema = new mongoose.Schema({
email: {type: String, index: true, unique: true, required: true, trim: true},
password: {type: String, default: "", trim: true},
}, {
timestamps: {createdAt: "created_at", updatedAt: false},
});

UserSchema.static("findByEmail", async function(email) {
return await this.findOne({ email });
});

UserSchema.static("register", async function(email, password) {
password = await bcrypt.hash(password, 12);
return await this.create({email, password});
});

UserSchema.method("isPassword", async function(password) {
return await bcrypt.compare(password, this.password);
});

module.exports = mongoose.model("User", UserSchema);
58 changes: 58 additions & 0 deletions src/userModel.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
const mongoose = require("./mongoClient");
const User = require("./userModel");

describe("UserModel", () => {
const existingEmail = "existing.user" + Math.random() + "@test.com";
const existingPassword = "supersecret";

beforeAll(async () => {
await User.register(existingEmail, existingPassword);
});

afterAll(async () => {
await require("mongoose").disconnect();
});

it("should register new user successfully", async () => {
const email = "unique.email+" + Math.random() + "test.com";
const pass = "supersecret";

const newUser = await User.register(email, pass);

expect(newUser).not.toBeNull();
expect(newUser.email).toBe(email);
expect(newUser.password).not.toBe(pass);

expect(await newUser.isPassword(pass)).toBe(true);
});

it("should not register new user because email already exist", async () => {
const email = "unique.email+" + Math.random() + "test.com";
const pass = "supersecret";

// first attempt is successful
const firstAttempt = await User.register(email, pass);

expect(firstAttempt).not.toBeNull();
expect(firstAttempt.email).toBe(email);
expect(firstAttempt.password).not.toBe(pass);

// second attempt is ending with throws exception
await expect((async () => {
await User.register(email, pass);
})()).rejects.toThrow(mongoose.MongoError);

});

it("should found existing user and check his password", async () => {

const existingUser = await User.findByEmail(existingEmail);

expect(existingUser).not.toBeNull();
expect(existingUser.email).toBe(existingEmail);
expect(existingUser.password).not.toBe(existingPassword);

expect(await existingUser.isPassword(existingPassword)).toBe(true);
});

});