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
2 changes: 2 additions & 0 deletions app/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@
angular.module("app", [

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

where are tests?

"ngRoute",
"chatApp.DataModel",
"chatApp.UserSession",

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please, do not split application into such modules.
Module should include services, controllers, directives etc.
For our task it is enough to have 1 module called "app"

"chatApp.UserList",
"chatApp.MessageSender",
"chatApp.MessageList"
]);

Expand Down
29 changes: 27 additions & 2 deletions app/components/data-model/DataModel.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@
var user = users[i];
for (var j = 0; j < 10; j++) {
messages.push({
messageId: i * 100 + j,
messageId: messages.length,
user: user,
messageText: 'Message #' + j + ' from User #' + i,
messageText: 'Message #' + j + ' from User #' + i + ':smile: :cat:',
messageDate : new Date()
});
}
Expand All @@ -32,14 +32,39 @@

module.service('DataModelService', function() {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is better to split the service into 2 services: users and messages.
In this case it will be easier to test them

var self = this;
this.activeUser = null;
this.users = generateUsers();
this.messages = generateMessages(this.users);
this.isLoggedIn = function() {
return (self.activeUser !== null);
};
this.getActiveUser = function() {
return self.activeUser;
};
this.setActiveUser = function(userName, password) {
self.activeUser = {
userId: self.users.length,
userName: userName
};
self.users.push(self.activeUser);
};
this.getUsers = function() {
return self.users;
};
this.getMessages = function() {
return self.messages;
};
this._getNextMessageId = function() {
return this.messages.length;
};
this.postMessage = function(messageText) {
self.messages.push({
messageId: self._getNextMessageId(),
user: self.activeUser,
messageText: messageText,
messageDate : new Date()
});
};
});

})();
2 changes: 1 addition & 1 deletion app/components/message-list/MessageList.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
(function () {
'use strict';

var module = angular.module('chatApp.MessageList', ['chatApp.DataModel']);
var module = angular.module('chatApp.MessageList', ['chatApp.DataModel', 'dbaq.emoji', 'ngSanitize']);

module.controller('MessagesController', function($scope, DataModelService) {
$scope.messageList = 'List of Messages';

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't move constants to controller. Feel free to hardcode them inside templates. If you would like to support more then 1 language, then take a look at angular-translate module.

Expand Down
2 changes: 1 addition & 1 deletion app/components/message-list/message-list-template.html
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<div class="chat-messages">
<div class="row message clearfix" ng-repeat="message in messages">
<div class="col-xs-2 username">{{message.user.userName}} - ({{message.user.userId}})</div>
<div class="col-xs-7 text">{{message.messageText}}</div>
<div class="col-xs-7 text" ng-bind-html="message.messageText | emoji"></div>
<div class="col-xs-3 time">{{message.messageDate | date: 'shortTime'}}</div>
</div>
</div>
27 changes: 27 additions & 0 deletions app/components/message-sender/MessageSender.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
(function () {
'use strict';

var module = angular.module('chatApp.MessageSender', ['chatApp.DataModel']);

module.controller('MessageSenderController', function($scope, DataModelService) {
$scope.isLoggedIn = function() {
return DataModelService.isLoggedIn();
};
$scope.messageText = '';
$scope.postMessage = function() {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How do you validate the form?
Have you tried to send form instance and check $invalid property?

DataModelService.postMessage($scope.messageText);
$scope.messageText = '';
};
}
);

module.directive('messagesender', [function() {
var directive = {};
directive.restrict = 'E';
directive.templateUrl = 'components/message-sender/message-sender-template.html';
directive.controller = 'MessageSenderController';
directive.controllerAs = 'messagesenderCtrl';
return directive;
}]);

})();
9 changes: 9 additions & 0 deletions app/components/message-sender/message-sender-template.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<div ng-controller="MessageSenderController" ng-show="isLoggedIn()">
<div>
<h2>New Message</h2>
<form name="messageSenderForm" ng-submit="postMessage()">

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

to prevent default HTML5 validation messages use novalidate attribute

<input type="text" name="test" ng-model="messageText" required>
<input type="submit">
</form>
</div>
</div>
29 changes: 29 additions & 0 deletions app/components/user-session/UserSession.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
(function () {
'use strict';

var module = angular.module('chatApp.UserSession', ['chatApp.DataModel']);

module.controller('LoginController', function($scope, DataModelService) {
$scope.isLoggedIn = function() {
return DataModelService.isLoggedIn();
};
$scope.userName = '';
$scope.password = '';
$scope.login = function() {
DataModelService.setActiveUser($scope.userName, $scope.password);
$scope.userName = '';

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it is better to move this logic into separate function
the code will look better

$scope.password = '';
};
}
);

module.directive('login', [function() {
var directive = {};
directive.restrict = 'E';
directive.templateUrl = 'components/user-session/login-template.html';
directive.controller = 'LoginController';
directive.controllerAs = 'loginCtrl';
return directive;
}]);

})();
12 changes: 12 additions & 0 deletions app/components/user-session/login-template.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<div ng-controller="LoginController" ng-hide="isLoggedIn()">
<h2>Log In for leaving new messages</h2>
<form name="loginForm" ng-submit="login()">
<label>User Name:</label>
<input type="text" name="userName" ng-model="userName" required>
<br/>
<label>Password:</label>
<input type="password" name="password" ng-model="password" required>
<br/>
<input type="submit" value="Log In">
</form>
</div>
4 changes: 4 additions & 0 deletions app/templates/chat/messages.html
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,8 @@

<messagelist></messagelist>

<messagesender></messagesender>

<login></login>

</div>
73 changes: 73 additions & 0 deletions specs/DataModelServiceSpec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
describe("data model service", function () {
var sut;

var ACTIVE_USER_NAME = 'ACTIVE_USER_NAME';
var MESSAGE_TEXT = 'MESSAGE_TEXT';

beforeEach(function () {
module("chatApp.DataModel");
});

beforeEach(inject(function (DataModelService) {
sut = DataModelService;
}));

it("will return 100 users", function () {
expect(sut.getUsers().length).toBe(100);
});

it("will return 1000 messages", function () {
expect(sut.getMessages().length).toBe(1000);
});

it("will be not logged in", function () {
expect(sut.isLoggedIn()).toBe(false);
});

it("won't have an active user", function () {
expect(sut.getActiveUser()).toBe(null);
});

describe('setActiveUser function', function() {
beforeEach(function() {
sut.setActiveUser(ACTIVE_USER_NAME);
});

it("should be logged in", function() {
expect(sut.isLoggedIn()).toBe(true);
});

it("active user must be set", function() {
//expect(sut.getActiveUser()).toBeNot(null);
});

it("active user name must be valid", function() {
expect(sut.getActiveUser().userName).toBe(ACTIVE_USER_NAME);
});

it("will return 100+1 users", function () {
expect(sut.getUsers().length).toBe(101);
});

});

describe('postMessage function', function() {
beforeEach(function() {
sut.setActiveUser(ACTIVE_USER_NAME);
sut.postMessage(MESSAGE_TEXT);
});

it("will return 1000+1 messages", function () {
expect(sut.getMessages().length).toBe(1001);
});

it("last message text must be known", function () {
expect(sut.getMessages()[sut.getMessages().length - 1].messageText).toBe(MESSAGE_TEXT);
});

it("last message user's name must be active user's", function () {
expect(sut.getMessages()[sut.getMessages().length - 1].user.userName).toBe(ACTIVE_USER_NAME);
});

});
});
51 changes: 51 additions & 0 deletions specs/LoginControllerSpec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
describe("login controller", function () {
var sut, mockDataModelService;

var USER_NAME = 'USER_NAME';
var PASSWORD = 'PASSWORD';

beforeEach(function () {
module("chatApp.UserSession");

mockDataModelService = {
isLoggedIn: jasmine.createSpy(),
setActiveUser: jasmine.createSpy()
};
});

beforeEach(inject(function ($controller, $rootScope) {
sut = $rootScope.$new();
$controller("LoginController", {
$scope: sut,
DataModelService: mockDataModelService
});
}));

describe('isLoggedIn function',function() {
beforeEach(function() {
sut.isLoggedIn();
});

it("should call DataModelService isLoggedIn function", function () {
expect(mockDataModelService.isLoggedIn).toHaveBeenCalled();
});
});

describe('login function',function() {
beforeEach(function() {
sut.userName = USER_NAME;
sut.password = PASSWORD;
sut.login();
});

it("should call DataModelService setActiveUser function", function () {
expect(mockDataModelService.setActiveUser).toHaveBeenCalledWith(USER_NAME, PASSWORD);
});

afterEach(function() {
expect(sut.userName).toEqual('');
expect(sut.password).toEqual('');
});
});

});
48 changes: 48 additions & 0 deletions specs/MessageSenderControllerSoec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
describe("message sender controller", function () {
var sut, mockDataModelService;

var MESSAGE_TEXT = 'MESSAGE-TEXT';

beforeEach(function () {
module("chatApp.MessageSender");

mockDataModelService = {
isLoggedIn: jasmine.createSpy(),
postMessage: jasmine.createSpy()
};
});

beforeEach(inject(function ($controller, $rootScope) {
sut = $rootScope.$new();
$controller("MessageSenderController", {
$scope: sut,
DataModelService: mockDataModelService
});
}));

describe('isLoggedIn function',function() {
beforeEach(function() {
sut.isLoggedIn();
});

it("should call DataModelService isLoggedIn function", function () {
expect(mockDataModelService.isLoggedIn).toHaveBeenCalled();
});
});

describe('postMessage function',function() {
beforeEach(function() {
sut.messageText = MESSAGE_TEXT;
sut.postMessage();
});

it("should call DataModelService postMessage function", function () {
expect(mockDataModelService.postMessage).toHaveBeenCalledWith(MESSAGE_TEXT);
});

afterEach(function() {
expect(sut.messageText).toEqual('');
});
});

});
25 changes: 25 additions & 0 deletions specs/MessagesControllerSpec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
describe("messages controller", function () {
var sut, mockDataModelService;

beforeEach(function () {
module("chatApp.MessageList");

mockDataModelService = {
getMessages: jasmine.createSpy()
};
});

beforeEach(inject(function ($controller, $rootScope) {
sut = $rootScope.$new();
$controller("MessagesController", {
$scope: sut,
DataModelService: mockDataModelService
});
}));

it("should call DataModelService getMessages function", function () {
expect(mockDataModelService.getMessages).toHaveBeenCalled();
});

});

24 changes: 24 additions & 0 deletions specs/UsersControllerSpc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
describe("users controller", function () {
var sut, mockDataModelService;

beforeEach(function () {
module("chatApp.UserList");

mockDataModelService = {
getUsers: jasmine.createSpy()
};
});

beforeEach(inject(function ($controller, $rootScope) {
sut = $rootScope.$new();
$controller("UsersController", {
$scope: sut,
DataModelService: mockDataModelService
});
}));

it("should call DataModelService getUsers function", function () {
expect(mockDataModelService.getUsers).toHaveBeenCalled();
});

});