BAEL-797 fixing unit test

This commit is contained in:
tschiman 2017-04-29 20:47:35 -06:00
parent bf0c42c8d6
commit f23b54220f
11 changed files with 104 additions and 233 deletions

View File

@ -76,7 +76,10 @@ export class BookListComponent implements OnInit {
let book: Book = this.books[bookIndex]; let book: Book = this.books[bookIndex];
this.httpService.deleteBook(book, this.principal.credentials) this.httpService.deleteBook(book, this.principal.credentials)
.subscribe(() => { .subscribe(() => {
if (this.selectedBook !== null && this.books[bookIndex].id === this.selectedBook.id) {this.selectedBook = null;} if (this.selectedBook !== null && this.books[bookIndex].id === this.selectedBook.id) {
this.selectedBook = null;
this.onBookSelected.emit(this.selectedBook);
}
this.books.splice(bookIndex, 1); //remove the book at this index; this.books.splice(bookIndex, 1); //remove the book at this index;
this.newBooks.splice(bookIndex, 1); //remove the editing book at this index this.newBooks.splice(bookIndex, 1); //remove the editing book at this index

View File

@ -0,0 +1,17 @@
package com.baeldung.spring.cloud.bootstrap.gateway;
import org.springframework.boot.web.servlet.ErrorPage;
import org.springframework.boot.web.servlet.ErrorPageRegistrar;
import org.springframework.boot.web.servlet.ErrorPageRegistry;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
@Component
public class ErrorPageConfig implements ErrorPageRegistrar {
@Override
public void registerErrorPages(ErrorPageRegistry registry) {
registry.addErrorPages(new ErrorPage(HttpStatus.NOT_FOUND, "/"));
}
}

View File

@ -29,7 +29,7 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter {
.httpBasic() .httpBasic()
.and() .and()
.authorizeRequests() .authorizeRequests()
.antMatchers("/*").permitAll() .antMatchers("/*.js","/*.html","/*.ico", "/*").permitAll()
.antMatchers("/book-service/books").permitAll() .antMatchers("/book-service/books").permitAll()
.antMatchers("/zipkin/**").permitAll() .antMatchers("/zipkin/**").permitAll()
.antMatchers("/eureka/**").hasRole("ADMIN") .antMatchers("/eureka/**").hasRole("ADMIN")

View File

@ -75,28 +75,28 @@ module.exports = module.exports.toString();
/***/ 149: /***/ 149:
/***/ (function(module, exports) { /***/ (function(module, exports) {
module.exports = "<nav class=\"navbar navbar-toggleable-md navbar-inverse fixed-top bg-inverse\">\n <button class=\"navbar-toggler navbar-toggler-right\" type=\"button\" data-toggle=\"collapse\" data-target=\"#navbarCollapse\" aria-controls=\"navbarCollapse\" aria-expanded=\"false\" aria-label=\"Toggle navigation\">\n <span class=\"navbar-toggler-icon\"></span>\n </button>\n <a class=\"navbar-brand\" href=\"#\">Book Rater <span *ngIf=\"principal.isAdmin()\">Admin</span></a>\n <div class=\"collapse navbar-collapse\" id=\"navbarCollapse\">\n <ul class=\"navbar-nav mr-auto\">\n </ul>\n <div *ngIf=\"!principal.authenticated; then loginForm else loginMessage\"></div>\n <ng-template #loginForm>\n <form (ngSubmit)=\"onLogin(f)\" class=\"form-inline mt-2 mt-md-0\" #f=\"ngForm\">\n <input name=\"username\" [(ngModel)]=\"credentials.username\" required class=\"form-control mr-sm-2\" type=\"text\" placeholder=\"Username\">\n <input name=\"password\" [(ngModel)]=\"credentials.password\" required class=\"form-control mr-sm-2\" type=\"password\" placeholder=\"Password\">\n <button class=\"btn btn-outline-success my-2 my-sm-0\" type=\"submit\" [disabled]=\"!f.valid\">Login</button>\n </form>\n </ng-template>\n <ng-template #loginMessage>\n <button type=\"button\" class=\"btn btn-link\" (click)=\"onLogout()\">Logout</button>\n </ng-template>\n <div *ngIf=\"loginFailed\">\n <div class=\"alert alert-warning\">Login Failed</div>\n </div>\n </div>\n</nav>\n\n<div class=\"jumbotron\">\n <div class=\"container\">\n <h1>Book Rater App</h1>\n <p *ngIf=\"!principal.authenticated\" class=\"lead\">Anyone can view the books.</p>\n <p *ngIf=\"principal.authenticated && !principal.isAdmin()\" class=\"lead\">Users can view and create ratings</p>\n <p *ngIf=\"principal.isAdmin()\" class=\"lead\">Admins can do anything!</p>\n </div>\n</div>\n\n<section class=\"books\">\n <div class=\"container\">\n <div class=\"row\">\n <div class=\"col-md\">\n <div class=\"row\">\n <div class=\"col-md-12\">\n <app-book-list [principal]=\"principal\" (onBookSelected)=\"selectBook($event)\"></app-book-list>\n </div>\n </div>\n </div>\n <div *ngIf=\"selectedBook != null\" class=\"col-md-3\">\n <app-book-detail [selectedBook]=\"selectedBook\" [principal]=\"principal\" (closeBook)=\"closeBookDetail()\"></app-book-detail>\n </div>\n </div>\n </div>\n</section>\n" module.exports = "<nav class=\"navbar navbar-toggleable-md navbar-inverse fixed-top bg-inverse\">\r\n <button class=\"navbar-toggler navbar-toggler-right\" type=\"button\" data-toggle=\"collapse\" data-target=\"#navbarCollapse\" aria-controls=\"navbarCollapse\" aria-expanded=\"false\" aria-label=\"Toggle navigation\">\r\n <span class=\"navbar-toggler-icon\"></span>\r\n </button>\r\n <a class=\"navbar-brand\" href=\"#\">Book Rater <span *ngIf=\"principal.isAdmin()\">Admin</span></a>\r\n <div class=\"collapse navbar-collapse\" id=\"navbarCollapse\">\r\n <ul class=\"navbar-nav mr-auto\">\r\n </ul>\r\n <div *ngIf=\"!principal.authenticated; then loginForm else loginMessage\"></div>\r\n <ng-template #loginForm>\r\n <form (ngSubmit)=\"onLogin(f)\" class=\"form-inline mt-2 mt-md-0\" #f=\"ngForm\">\r\n <input name=\"username\" [(ngModel)]=\"credentials.username\" required class=\"form-control mr-sm-2\" type=\"text\" placeholder=\"Username\">\r\n <input name=\"password\" [(ngModel)]=\"credentials.password\" required class=\"form-control mr-sm-2\" type=\"password\" placeholder=\"Password\">\r\n <button class=\"btn btn-outline-success my-2 my-sm-0\" type=\"submit\" [disabled]=\"!f.valid\">Login</button>\r\n </form>\r\n </ng-template>\r\n <ng-template #loginMessage>\r\n <button type=\"button\" class=\"btn btn-link\" (click)=\"onLogout()\">Logout</button>\r\n </ng-template>\r\n <div *ngIf=\"loginFailed\">\r\n <div class=\"alert alert-warning\">Login Failed</div>\r\n </div>\r\n </div>\r\n</nav>\r\n\r\n<div class=\"jumbotron\">\r\n <div class=\"container\">\r\n <h1>Book Rater App</h1>\r\n <p *ngIf=\"!principal.authenticated\" class=\"lead\">Anyone can view the books.</p>\r\n <p *ngIf=\"principal.authenticated && !principal.isAdmin()\" class=\"lead\">Users can view and create ratings</p>\r\n <p *ngIf=\"principal.isAdmin()\" class=\"lead\">Admins can do anything!</p>\r\n </div>\r\n</div>\r\n\r\n<section class=\"books\">\r\n <div class=\"container\">\r\n <div class=\"row\">\r\n <div class=\"col-md\">\r\n <div class=\"row\">\r\n <div class=\"col-md-12\">\r\n <app-book-list [principal]=\"principal\" (onBookSelected)=\"selectBook($event)\"></app-book-list>\r\n </div>\r\n </div>\r\n </div>\r\n <div *ngIf=\"selectedBook != null\" class=\"col-md-3\">\r\n <app-book-detail [selectedBook]=\"selectedBook\" [principal]=\"principal\" (closeBook)=\"closeBookDetail()\"></app-book-detail>\r\n </div>\r\n </div>\r\n </div>\r\n</section>\r\n"
/***/ }), /***/ }),
/***/ 150: /***/ 150:
/***/ (function(module, exports) { /***/ (function(module, exports) {
module.exports = "<div class=\"card\">\n <div class=\"card-block\">\n <button type=\"button\" class=\"close\" aria-label=\"Close\" (click)=\"closeBookDetail()\">\n <span aria-hidden=\"true\">&times;</span>\n </button>\n <h4 class=\"card-title\">Title: {{selectedBook.title}}</h4>\n <h6 class=\"card-subtitle mb-2 text-muted\">Author: {{selectedBook.author}}</h6>\n <p class=\"card-text\">A quick summary of the book</p>\n <app-rating *ngIf=\"principal.authenticated\" [bookId]=\"selectedBook.id\" [principal]=\"principal\"></app-rating>\n </div>\n</div>\n" module.exports = "<div class=\"card\">\r\n <div class=\"card-block\">\r\n <button type=\"button\" class=\"close\" aria-label=\"Close\" (click)=\"closeBookDetail()\">\r\n <span aria-hidden=\"true\">&times;</span>\r\n </button>\r\n <h4 class=\"card-title\">Title: {{selectedBook.title}}</h4>\r\n <h6 class=\"card-subtitle mb-2 text-muted\">Author: {{selectedBook.author}}</h6>\r\n <p class=\"card-text\">A quick summary of the book</p>\r\n <app-rating *ngIf=\"principal.authenticated\" [bookId]=\"selectedBook.id\" [principal]=\"principal\"></app-rating>\r\n </div>\r\n</div>\r\n"
/***/ }), /***/ }),
/***/ 151: /***/ 151:
/***/ (function(module, exports) { /***/ (function(module, exports) {
module.exports = "<div class=\"col-md-12\" *ngFor=\"let book of books; let i = index;\" (click)=\"selectBook(book)\">\n <div class=\"card\">\n <div class=\"card-block\">\n <div *ngIf=\"booksToEdit.indexOf(i) === -1 ; then bookView else bookEdit\"></div>\n <ng-template #bookView>\n <button appClickStopPropagation *ngIf=\"principal.isAdmin()\" type=\"button\" class=\"btn btn-danger custom-close\" (click)=\"delete(i)\">Delete</button>\n <button appClickStopPropagation *ngIf=\"principal.isAdmin()\" type=\"button\" class=\"btn btn-warning custom-close\" (click)=\"editBook(i)\">Edit</button>\n <h4 class=\"card-title\">Title: {{book.title}}</h4>\n <h6 class=\"card-subtitle mb-2 text-muted\">Author: {{book.author}}</h6>\n </ng-template>\n <ng-template #bookEdit>\n <button appClickStopPropagation type=\"button\" class=\"btn btn-secondary custom-close\" (click)=\"cancelEditBook(i)\">Cancel</button>\n <form appClickStopPropagation (ngSubmit)=\"saveBook(i, newBooks[i])\" class=\"mt-2 mt-md-0\" #f1=\"ngForm\">\n <div class=\"form-group\">\n <label for=\"title\">Title:</label>\n <input id=\"title\" name=\"title\" [(ngModel)]=\"newBooks[i].title\" required class=\"form-control mr-sm-2\" type=\"text\">\n </div>\n <div class=\"form-group\">\n <label for=\"author\">Author:</label>\n <input id=\"author\" name=\"author\" [(ngModel)]=\"newBooks[i].author\" required class=\"form-control mr-sm-2\" type=\"text\">\n </div>\n <button class=\"btn btn-outline-success my-2 my-sm-0\" type=\"submit\" [disabled]=\"!f1.valid\">Save</button>\n </form>\n </ng-template>\n\n </div>\n </div>\n</div>\n<div *ngIf=\"principal.isAdmin()\" class=\"col-md-12\">\n <div class=\"card\">\n <div class=\"card-block\">\n <div *ngIf=\"!isAddNewBook; then bookPlaceHolder else bookAdd\"></div>\n <ng-template #bookPlaceHolder>\n <h4 (click)=\"activateAddNewBook()\" class=\"card-title center-block\">Add New Book</h4>\n </ng-template>\n <ng-template #bookAdd>\n <button appClickStopPropagation type=\"button\" class=\"btn btn-secondary custom-close\" (click)=\"cancelAddBook()\">Cancel</button>\n <form appClickStopPropagation (ngSubmit)=\"addNewBook(newBook, titleNewBook)\" class=\"mt-2 mt-md-0\" #f2=\"ngForm\">\n <div class=\"form-group\">\n <label for=\"titleNewBook\">Title:</label>\n <input id=\"titleNewBook\" name=\"title\" [(ngModel)]=\"newBook.title\" required class=\"form-control mr-sm-2\" type=\"text\" #titleNewBook>\n </div>\n <div class=\"form-group\">\n <label for=\"authorNewBook\">Author:</label>\n <input id=\"authorNewBook\" name=\"author\" [(ngModel)]=\"newBook.author\" required class=\"form-control mr-sm-2\" type=\"text\">\n </div>\n <button class=\"btn btn-outline-success my-2 my-sm-0\" type=\"submit\" [disabled]=\"!f2.valid\">Save</button>\n </form>\n </ng-template>\n\n </div>\n </div>\n\n</div>\n" module.exports = "<div class=\"col-md-12\" *ngFor=\"let book of books; let i = index;\" (click)=\"selectBook(book)\">\r\n <div class=\"card\">\r\n <div class=\"card-block\">\r\n <div *ngIf=\"booksToEdit.indexOf(i) === -1 ; then bookView else bookEdit\"></div>\r\n <ng-template #bookView>\r\n <button appClickStopPropagation *ngIf=\"principal.isAdmin()\" type=\"button\" class=\"btn btn-danger custom-close\" (click)=\"delete(i)\">Delete</button>\r\n <button appClickStopPropagation *ngIf=\"principal.isAdmin()\" type=\"button\" class=\"btn btn-warning custom-close\" (click)=\"editBook(i)\">Edit</button>\r\n <h4 class=\"card-title\">Title: {{book.title}}</h4>\r\n <h6 class=\"card-subtitle mb-2 text-muted\">Author: {{book.author}}</h6>\r\n </ng-template>\r\n <ng-template #bookEdit>\r\n <button appClickStopPropagation type=\"button\" class=\"btn btn-secondary custom-close\" (click)=\"cancelEditBook(i)\">Cancel</button>\r\n <form appClickStopPropagation (ngSubmit)=\"saveBook(i, newBooks[i])\" class=\"mt-2 mt-md-0\" #f1=\"ngForm\">\r\n <div class=\"form-group\">\r\n <label for=\"title\">Title:</label>\r\n <input id=\"title\" name=\"title\" [(ngModel)]=\"newBooks[i].title\" required class=\"form-control mr-sm-2\" type=\"text\">\r\n </div>\r\n <div class=\"form-group\">\r\n <label for=\"author\">Author:</label>\r\n <input id=\"author\" name=\"author\" [(ngModel)]=\"newBooks[i].author\" required class=\"form-control mr-sm-2\" type=\"text\">\r\n </div>\r\n <button class=\"btn btn-outline-success my-2 my-sm-0\" type=\"submit\" [disabled]=\"!f1.valid\">Save</button>\r\n </form>\r\n </ng-template>\r\n\r\n </div>\r\n </div>\r\n</div>\r\n<div *ngIf=\"principal.isAdmin()\" class=\"col-md-12\">\r\n <div class=\"card\">\r\n <div class=\"card-block\">\r\n <div *ngIf=\"!isAddNewBook; then bookPlaceHolder else bookAdd\"></div>\r\n <ng-template #bookPlaceHolder>\r\n <h4 (click)=\"activateAddNewBook()\" class=\"card-title center-block\">Add New Book</h4>\r\n </ng-template>\r\n <ng-template #bookAdd>\r\n <button appClickStopPropagation type=\"button\" class=\"btn btn-secondary custom-close\" (click)=\"cancelAddBook()\">Cancel</button>\r\n <form appClickStopPropagation (ngSubmit)=\"addNewBook(newBook, titleNewBook)\" class=\"mt-2 mt-md-0\" #f2=\"ngForm\">\r\n <div class=\"form-group\">\r\n <label for=\"titleNewBook\">Title:</label>\r\n <input id=\"titleNewBook\" name=\"title\" [(ngModel)]=\"newBook.title\" required class=\"form-control mr-sm-2\" type=\"text\" #titleNewBook>\r\n </div>\r\n <div class=\"form-group\">\r\n <label for=\"authorNewBook\">Author:</label>\r\n <input id=\"authorNewBook\" name=\"author\" [(ngModel)]=\"newBook.author\" required class=\"form-control mr-sm-2\" type=\"text\">\r\n </div>\r\n <button class=\"btn btn-outline-success my-2 my-sm-0\" type=\"submit\" [disabled]=\"!f2.valid\">Save</button>\r\n </form>\r\n </ng-template>\r\n\r\n </div>\r\n </div>\r\n\r\n</div>\r\n"
/***/ }), /***/ }),
/***/ 152: /***/ 152:
/***/ (function(module, exports) { /***/ (function(module, exports) {
module.exports = "Ratings:\n<div *ngFor=\"let rating of ratings; let i = index;\" class=\"row\">\n <div class=\"col-md-10\">\n <div class=\"progress\" [ngClass]=\"{'selected': principal.isAdmin() && rating === newRating, 'rating': principal.isAdmin()}\" (click)=\"selectRating(rating)\">\n <div class=\"progress-bar bg-success\" role=\"progressbar\" [style.width]=\"findWidth(rating)\" [attr.aria-valuenow]=\"rating.stars\" aria-valuemin=\"0\" aria-valuemax=\"5\"></div>\n </div>\n </div>\n <div class=\"col-md-1\">\n <button *ngIf=\"principal?.isAdmin()\" type=\"button\" class=\"close\" aria-label=\"Close\" (click)=\"deleteRating(i)\">\n <span aria-hidden=\"true\">&times;</span>\n </button>\n </div>\n</div>\n\n<form (ngSubmit)=\"onSaveRating(f)\" #f=\"ngForm\">\n <div class=\"form-check form-check-inline\" *ngFor=\"let star of stars; let i = index;\">\n <label class=\"form-check-label\">\n <input class=\"form-check-input\" type=\"radio\" name=\"star\" [(ngModel)]=\"newRating.stars\" [value]=\"star\">{{star}}\n </label>\n </div>\n <button *ngIf=\"newRating.id === null\" type=\"submit\" class=\"btn btn-secondary\" [disabled]=\"!f.valid\">Add Rating</button>\n <button *ngIf=\"principal.isAdmin() && newRating.id !== null\" type=\"button\" class=\"btn btn-secondary\" (click)=\"updateRating()\">Save</button>\n <button *ngIf=\"principal.isAdmin() && newRating.id !== null\" type=\"button\" class=\"btn btn-secondary\" (click)=\"cancelSelection()\">Cancel</button>\n</form>\n\n" module.exports = "Ratings:\r\n<div *ngFor=\"let rating of ratings; let i = index;\" class=\"row\">\r\n <div class=\"col-md-10\">\r\n <div class=\"progress\" [ngClass]=\"{'selected': principal.isAdmin() && rating === newRating, 'rating': principal.isAdmin()}\" (click)=\"selectRating(rating)\">\r\n <div class=\"progress-bar bg-success\" role=\"progressbar\" [style.width]=\"findWidth(rating)\" [attr.aria-valuenow]=\"rating.stars\" aria-valuemin=\"0\" aria-valuemax=\"5\"></div>\r\n </div>\r\n </div>\r\n <div class=\"col-md-1\">\r\n <button *ngIf=\"principal?.isAdmin()\" type=\"button\" class=\"close\" aria-label=\"Close\" (click)=\"deleteRating(i)\">\r\n <span aria-hidden=\"true\">&times;</span>\r\n </button>\r\n </div>\r\n</div>\r\n\r\n<form (ngSubmit)=\"onSaveRating(f)\" #f=\"ngForm\">\r\n <div class=\"form-check form-check-inline\" *ngFor=\"let star of stars; let i = index;\">\r\n <label class=\"form-check-label\">\r\n <input class=\"form-check-input\" type=\"radio\" name=\"star\" [(ngModel)]=\"newRating.stars\" [value]=\"star\">{{star}}\r\n </label>\r\n </div>\r\n <button *ngIf=\"newRating.id === null\" type=\"submit\" class=\"btn btn-secondary\" [disabled]=\"!f.valid\">Add Rating</button>\r\n <button *ngIf=\"principal.isAdmin() && newRating.id !== null\" type=\"button\" class=\"btn btn-secondary\" (click)=\"updateRating()\">Save</button>\r\n <button *ngIf=\"principal.isAdmin() && newRating.id !== null\" type=\"button\" class=\"btn btn-secondary\" (click)=\"cancelSelection()\">Cancel</button>\r\n</form>\r\n\r\n"
/***/ }), /***/ }),
@ -563,6 +563,7 @@ var BookListComponent = (function () {
.subscribe(function () { .subscribe(function () {
if (_this.selectedBook !== null && _this.books[bookIndex].id === _this.selectedBook.id) { if (_this.selectedBook !== null && _this.books[bookIndex].id === _this.selectedBook.id) {
_this.selectedBook = null; _this.selectedBook = null;
_this.onBookSelected.emit(_this.selectedBook);
} }
_this.books.splice(bookIndex, 1); //remove the book at this index; _this.books.splice(bookIndex, 1); //remove the book at this index;
_this.newBooks.splice(bookIndex, 1); //remove the editing book at this index _this.newBooks.splice(bookIndex, 1); //remove the editing book at this index

File diff suppressed because one or more lines are too long

View File

@ -80,7 +80,7 @@ exports = module.exports = __webpack_require__(13)();
// module // module
exports.push([module.i, "/* You can add global styles to this file, and also import other style files */\n", ""]); exports.push([module.i, "/* You can add global styles to this file, and also import other style files */\r\n", ""]);
// exports // exports

View File

@ -1,201 +0,0 @@
package com.baeldung.spring.cloud.bootstrap.gateway;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import org.apache.http.entity.ContentType;
import org.junit.Assert;
import org.junit.Test;
import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.http.*;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
public class IntegrationLiveTest {
private TestRestTemplate testRestTemplate = new TestRestTemplate();
private String testUrl = "http://localhost:8080";
@Test
public void testAccess() throws Exception {
ResponseEntity<String> response = testRestTemplate.getForEntity(testUrl + "/book-service/books", String.class);
Assert.assertEquals(HttpStatus.OK, response.getStatusCode());
Assert.assertNotNull(response.getBody());
//try the protected resource and confirm the redirect to login
response = testRestTemplate.getForEntity(testUrl + "/book-service/books/1", String.class);
Assert.assertEquals(HttpStatus.FOUND, response.getStatusCode());
Assert.assertEquals("http://localhost:8080/login", response.getHeaders().get("Location").get(0));
//login as user/password
MultiValueMap<String, String> form = new LinkedMultiValueMap<>();
form.add("username", "user");
form.add("password", "password");
response = testRestTemplate.postForEntity(testUrl + "/login", form, String.class);
//extract the session from the cookie and propagate it to the next request
String sessionCookie = response.getHeaders().get("Set-Cookie").get(0).split(";")[0];
HttpHeaders headers = new HttpHeaders();
headers.add("Cookie", sessionCookie);
HttpEntity<String> httpEntity = new HttpEntity<>(headers);
addBook();
//request the protected resource
response = testRestTemplate.exchange(testUrl + "/book-service/books/1", HttpMethod.GET, httpEntity, String.class);
Assert.assertEquals(HttpStatus.OK, response.getStatusCode());
Assert.assertNotNull(response.getBody());
addRatings();
//request the admin protected resource to determine it is still protected
response = testRestTemplate.exchange(testUrl + "/rating-service/ratings", HttpMethod.GET, httpEntity, String.class);
Assert.assertEquals(HttpStatus.FORBIDDEN, response.getStatusCode());
//login as the admin
form.clear();
form.add("username", "admin");
form.add("password", "admin");
response = testRestTemplate.postForEntity(testUrl + "/login", form, String.class);
//extract the session from the cookie and propagate it to the next request
sessionCookie = response.getHeaders().get("Set-Cookie").get(0).split(";")[0];
headers = new HttpHeaders();
headers.add("Cookie", sessionCookie);
httpEntity = new HttpEntity<>(headers);
//request the protected resource
response = testRestTemplate.exchange(testUrl + "/rating-service/ratings", HttpMethod.GET, httpEntity, String.class);
Assert.assertEquals(HttpStatus.OK, response.getStatusCode());
Assert.assertNotNull(response.getBody());
//request the discovery resources as the admin
response = testRestTemplate.exchange(testUrl + "/discovery", HttpMethod.GET, httpEntity, String.class);
Assert.assertEquals(HttpStatus.OK, response.getStatusCode());
}
private void addRatings() {
//login as user/password
MultiValueMap<String, String> form = new LinkedMultiValueMap<>();
form.add("username", "user");
form.add("password", "password");
ResponseEntity<String> response = testRestTemplate.postForEntity(testUrl + "/login", form, String.class);
//extract the session from the cookie and propagate it to the next request
String sessionCookie = response.getHeaders().get("Set-Cookie").get(0).split(";")[0];
HttpHeaders headers = new HttpHeaders();
headers.add("Cookie", sessionCookie);
headers.add("ContentType", ContentType.APPLICATION_JSON.getMimeType());
Rating rating = new Rating(1L, 4);
HttpEntity<Rating> httpEntity = new HttpEntity<>(rating, headers);
//request the protected resource
ResponseEntity<Rating> bookResponse = testRestTemplate.postForEntity(testUrl + "/rating-service/ratings", httpEntity, Rating.class);
Assert.assertEquals(HttpStatus.OK, bookResponse.getStatusCode());
Assert.assertEquals(rating.getBookId(), bookResponse.getBody().getBookId());
Assert.assertEquals(rating.getStars(), bookResponse.getBody().getStars());
}
private void addBook(){
//login as user/password
MultiValueMap<String, String> form = new LinkedMultiValueMap<>();
form.add("username", "admin");
form.add("password", "admin");
ResponseEntity<String> response = testRestTemplate.postForEntity(testUrl + "/login", form, String.class);
//extract the session from the cookie and propagate it to the next request
String sessionCookie = response.getHeaders().get("Set-Cookie").get(0).split(";")[0];
HttpHeaders headers = new HttpHeaders();
headers.add("Cookie", sessionCookie);
headers.add("ContentType", ContentType.APPLICATION_JSON.getMimeType());
Book book = new Book("Baeldung", "How to spring cloud");
HttpEntity<Book> httpEntity = new HttpEntity<>(book, headers);
//request the protected resource
ResponseEntity<Book> bookResponse = testRestTemplate.postForEntity(testUrl + "/book-service/books", httpEntity, Book.class);
Assert.assertEquals(HttpStatus.OK, bookResponse.getStatusCode());
Assert.assertEquals(book.getAuthor(), bookResponse.getBody().getAuthor());
Assert.assertEquals(book.getTitle(), bookResponse.getBody().getTitle());
}
@JsonIgnoreProperties(ignoreUnknown = true)
public static class Book {
private Long id;
private String author;
private String title;
public Book() {
}
public Book(String author, String title) {
this.author = author;
this.title = title;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
}
@JsonIgnoreProperties(ignoreUnknown = true)
public static class Rating {
private Long id;
private Long bookId;
private int stars;
public Rating() {
}
public Rating(Long bookId, int stars) {
this.bookId = bookId;
this.stars = stars;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Long getBookId() {
return bookId;
}
public void setBookId(Long bookId) {
this.bookId = bookId;
}
public int getStars() {
return stars;
}
public void setStars(int stars) {
this.stars = stars;
}
}
}

View File

@ -1,28 +1,29 @@
package com.baeldung.spring.cloud.bootstrap.gateway; package com.baeldung.spring.cloud.bootstrap.gateway;
import static io.restassured.RestAssured.config; import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import io.restassured.RestAssured; import io.restassured.RestAssured;
import io.restassured.authentication.FormAuthConfig;
import io.restassured.config.RedirectConfig; import io.restassured.config.RedirectConfig;
import io.restassured.config.SessionConfig;
import io.restassured.filter.session.SessionFilter;
import io.restassured.http.ContentType; import io.restassured.http.ContentType;
import io.restassured.response.Response; import io.restassured.response.Response;
import org.junit.Assert; import org.junit.Assert;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import static io.restassured.RestAssured.config;
public class LiveTest { public class LiveTest {
private final String ROOT_URI = "http://localhost:8080"; private final String ROOT_URI = "http://localhost:8080";
private final FormAuthConfig formConfig = new FormAuthConfig("/login", "username", "password"); SessionFilter sessionFilter;
@Before @Before
public void setup() { public void setup() {
RestAssured.config = config().redirect(RedirectConfig.redirectConfig() RestAssured.config = config()
.followRedirects(false)); .redirect(RedirectConfig.redirectConfig().followRedirects(false))
.sessionConfig(new SessionConfig().sessionIdName("SESSION"));
} }
@Test @Test
@ -35,15 +36,16 @@ public class LiveTest {
@Test @Test
public void whenAccessProtectedResourceWithoutLogin_thenRedirectToLogin() { public void whenAccessProtectedResourceWithoutLogin_thenRedirectToLogin() {
final Response response = RestAssured.get(ROOT_URI + "/book-service/books/1"); final Response response = RestAssured.get(ROOT_URI + "/book-service/books/1");
Assert.assertEquals(HttpStatus.FOUND.value(), response.getStatusCode()); Assert.assertEquals(HttpStatus.UNAUTHORIZED.value(), response.getStatusCode());
Assert.assertEquals("http://localhost:8080/login", response.getHeader("Location"));
} }
@Test @Test
public void whenAccessProtectedResourceAfterLogin_thenSuccess() { public void whenAccessProtectedResourceAfterLogin_thenSuccess() {
SessionData sessionData = login();
final Response response = RestAssured.given() final Response response = RestAssured.given()
.auth() .auth().preemptive().basic("user", "password")
.form("user", "password", formConfig) .header("X-XSRF-TOKEN", sessionData.getCsrf())
.filter(sessionFilter)
.get(ROOT_URI + "/book-service/books/1"); .get(ROOT_URI + "/book-service/books/1");
Assert.assertEquals(HttpStatus.OK.value(), response.getStatusCode()); Assert.assertEquals(HttpStatus.OK.value(), response.getStatusCode());
Assert.assertNotNull(response.getBody()); Assert.assertNotNull(response.getBody());
@ -51,9 +53,11 @@ public class LiveTest {
@Test @Test
public void whenAccessAdminProtectedResource_thenForbidden() { public void whenAccessAdminProtectedResource_thenForbidden() {
SessionData sessionData = login();
final Response response = RestAssured.given() final Response response = RestAssured.given()
.auth() .auth().preemptive().basic("user", "password")
.form("user", "password", formConfig) .header("X-XSRF-TOKEN", sessionData.getCsrf())
.filter(sessionFilter)
.get(ROOT_URI + "/rating-service/ratings"); .get(ROOT_URI + "/rating-service/ratings");
Assert.assertEquals(HttpStatus.FORBIDDEN.value(), response.getStatusCode()); Assert.assertEquals(HttpStatus.FORBIDDEN.value(), response.getStatusCode());
@ -61,9 +65,11 @@ public class LiveTest {
@Test @Test
public void whenAdminAccessProtectedResource_thenSuccess() { public void whenAdminAccessProtectedResource_thenSuccess() {
SessionData sessionData = login();
final Response response = RestAssured.given() final Response response = RestAssured.given()
.auth() .auth().preemptive().basic("admin", "admin")
.form("admin", "admin", formConfig) .header("X-XSRF-TOKEN", sessionData.getCsrf())
.filter(sessionFilter)
.get(ROOT_URI + "/rating-service/ratings"); .get(ROOT_URI + "/rating-service/ratings");
Assert.assertEquals(HttpStatus.OK.value(), response.getStatusCode()); Assert.assertEquals(HttpStatus.OK.value(), response.getStatusCode());
Assert.assertNotNull(response.getBody()); Assert.assertNotNull(response.getBody());
@ -71,9 +77,11 @@ public class LiveTest {
@Test @Test
public void whenAdminAccessDiscoveryResource_thenSuccess() { public void whenAdminAccessDiscoveryResource_thenSuccess() {
SessionData sessionData = login();
final Response response = RestAssured.given() final Response response = RestAssured.given()
.auth() .auth().preemptive().basic("admin", "admin")
.form("admin", "admin", formConfig) .header("X-XSRF-TOKEN", sessionData.getCsrf())
.filter(sessionFilter)
.get(ROOT_URI + "/discovery"); .get(ROOT_URI + "/discovery");
Assert.assertEquals(HttpStatus.OK.value(), response.getStatusCode()); Assert.assertEquals(HttpStatus.OK.value(), response.getStatusCode());
} }
@ -83,10 +91,13 @@ public class LiveTest {
final Rating rating = new Rating(1L, 4); final Rating rating = new Rating(1L, 4);
SessionData sessionData = login();
// request the protected resource // request the protected resource
final Response ratingResponse = RestAssured.given() final Response ratingResponse = RestAssured.given()
.auth() .auth().preemptive().basic("admin", "admin")
.form("admin", "admin", formConfig) .header("X-XSRF-TOKEN", sessionData.getCsrf())
.filter(sessionFilter)
.and() .and()
.contentType(ContentType.JSON) .contentType(ContentType.JSON)
.body(rating) .body(rating)
@ -101,10 +112,13 @@ public class LiveTest {
public void whenAddnewBook_thenSuccess() { public void whenAddnewBook_thenSuccess() {
final Book book = new Book("Baeldung", "How to spring cloud"); final Book book = new Book("Baeldung", "How to spring cloud");
SessionData sessionData = login();
// request the protected resource // request the protected resource
final Response bookResponse = RestAssured.given() final Response bookResponse = RestAssured.given()
.auth() .auth().preemptive().basic("admin", "admin")
.form("admin", "admin", formConfig) .header("X-XSRF-TOKEN", sessionData.getCsrf())
.filter(sessionFilter)
.and() .and()
.contentType(ContentType.JSON) .contentType(ContentType.JSON)
.body(book) .body(book)
@ -195,4 +209,41 @@ public class LiveTest {
} }
} }
private SessionData login() {
sessionFilter = new SessionFilter();
Response getLoginResponse =
RestAssured.given().
filter(sessionFilter).
when().
get("/").
then().
extract().response();
return new SessionData(getLoginResponse.cookie("XSRF-TOKEN"), sessionFilter.getSessionId());
}
private class SessionData {
private String csrf;
private String session;
public SessionData(String csrf, String session) {
this.csrf = csrf;
this.session = session;
}
public String getCsrf() {
return csrf;
}
public void setCsrf(String csrf) {
this.csrf = csrf;
}
public String getSession() {
return session;
}
public void setSession(String session) {
this.session = session;
}
}
} }