@ -1,118 +0,0 @@ | |||||
namespace Microsoft.eShopOnContainers.Services.Ordering.Application.Commands | |||||
{ | |||||
using Domain.Repositories; | |||||
using MediatR; | |||||
using System.Linq; | |||||
using System; | |||||
using System.Threading.Tasks; | |||||
using Domain; | |||||
public class NewOrderRequestHandler | |||||
: IAsyncRequestHandler<NewOrderRequest, bool> | |||||
{ | |||||
private readonly IBuyerRepository _buyerRepository; | |||||
private readonly IOrderRepository _orderRepository; | |||||
public NewOrderRequestHandler(IBuyerRepository buyerRepository,IOrderRepository orderRepository) | |||||
{ | |||||
if (buyerRepository == null) | |||||
{ | |||||
throw new ArgumentNullException(nameof(buyerRepository)); | |||||
} | |||||
if (orderRepository == null) | |||||
{ | |||||
throw new ArgumentNullException(nameof(orderRepository)); | |||||
} | |||||
_buyerRepository = buyerRepository; | |||||
_orderRepository = orderRepository; | |||||
} | |||||
public async Task<bool> Handle(NewOrderRequest message) | |||||
{ | |||||
//find buyer/payment or add a new one buyer/payment | |||||
var buyer = await _buyerRepository.FindAsync(message.Buyer); | |||||
if (buyer == null) | |||||
{ | |||||
buyer = CreateBuyer(message); | |||||
} | |||||
var payment = GetExistingPaymentOrAddANewOne(buyer, message); | |||||
await _buyerRepository.UnitOfWork | |||||
.SaveChangesAsync(); | |||||
//create order for buyer and payment method | |||||
var order = CreateOrder(buyer.Id, payment.Id, 0); | |||||
order.SetAddress( new Address() | |||||
{ | |||||
City = message.City, | |||||
State = message.State, | |||||
Street = message.Street, | |||||
ZipCode = message.ZipCode | |||||
}); | |||||
foreach (var item in message.OrderItems) | |||||
{ | |||||
order.AddOrderItem(item); | |||||
} | |||||
_orderRepository.Add(order); | |||||
var result = await _orderRepository.UnitOfWork | |||||
.SaveChangesAsync(); | |||||
return result > 0; | |||||
} | |||||
Payment GetExistingPaymentOrAddANewOne(Buyer buyer, NewOrderRequest message) | |||||
{ | |||||
Payment payment = PaymentAlreadyExist(buyer, message); | |||||
if (payment == null) | |||||
{ | |||||
payment = CreatePayment(message); | |||||
buyer.Payments.Add(payment); | |||||
} | |||||
return payment; | |||||
} | |||||
Payment PaymentAlreadyExist(Domain.Buyer buyer, NewOrderRequest message) | |||||
{ | |||||
return buyer.Payments | |||||
.SingleOrDefault(p => | |||||
{ | |||||
return p.CardHolderName == message.CardHolderName | |||||
&& | |||||
p.CardNumber == message.CardNumber | |||||
&& | |||||
p.Expiration == message.CardExpiration | |||||
&& | |||||
p.SecurityNumber == message.CardSecurityNumber; | |||||
}); | |||||
} | |||||
Buyer CreateBuyer(NewOrderRequest message) | |||||
{ | |||||
return _buyerRepository.Add( | |||||
new Buyer(message.Buyer)); | |||||
} | |||||
Order CreateOrder(int buyerId, int paymentId, int addressId) | |||||
{ | |||||
return new Order(buyerId, paymentId); | |||||
} | |||||
Payment CreatePayment(NewOrderRequest message) | |||||
{ | |||||
return new Payment(message.CardNumber, message.CardSecurityNumber, message.CardHolderName, message.CardExpiration, message.CardTypeId); | |||||
} | |||||
} | |||||
} |
@ -1,48 +0,0 @@ | |||||
namespace Microsoft.eShopOnContainers.Services.Ordering.Application.Commands | |||||
{ | |||||
using System; | |||||
using MediatR; | |||||
using Domain; | |||||
using System.Collections; | |||||
using System.Collections.Generic; | |||||
public class NewOrderRequest | |||||
:IAsyncRequest<bool> | |||||
{ | |||||
private readonly List<OrderItem> _orderItems; | |||||
public string City { get; set; } | |||||
public string Street { get; set; } | |||||
public string State { get; set; } | |||||
public string Country { get; set; } | |||||
public string ZipCode { get; set; } | |||||
public string CardNumber { get; set; } | |||||
public string CardHolderName { get; set; } | |||||
public DateTime CardExpiration { get; set; } | |||||
public string CardSecurityNumber { get; set; } | |||||
public int CardTypeId { get; set; } | |||||
public string Buyer { get; set; } | |||||
public IEnumerable<OrderItem> OrderItems => _orderItems; | |||||
public void AddOrderItem(OrderItem item) | |||||
{ | |||||
_orderItems.Add(item); | |||||
} | |||||
public NewOrderRequest() | |||||
{ | |||||
_orderItems = new List<OrderItem>(); | |||||
} | |||||
} | |||||
} |
@ -1,34 +0,0 @@ | |||||
namespace Microsoft.eShopOnContainers.Services.Ordering.Application.Decorators | |||||
{ | |||||
using Extensions.Logging; | |||||
using MediatR; | |||||
using System.Threading.Tasks; | |||||
public class LogDecorator<TRequest, TResponse> | |||||
: IAsyncRequestHandler<TRequest, TResponse> | |||||
where TRequest : IAsyncRequest<TResponse> | |||||
{ | |||||
private readonly IAsyncRequestHandler<TRequest, TResponse> _inner; | |||||
private readonly ILogger<LogDecorator<TRequest, TResponse>> _logger; | |||||
public LogDecorator( | |||||
IAsyncRequestHandler<TRequest, TResponse> inner, | |||||
ILogger<LogDecorator<TRequest, TResponse>> logger) | |||||
{ | |||||
_inner = inner; | |||||
_logger = logger; | |||||
} | |||||
public async Task<TResponse> Handle(TRequest message) | |||||
{ | |||||
_logger.LogInformation($"Executing command {_inner.GetType().FullName}"); | |||||
var response = await _inner.Handle(message); | |||||
_logger.LogInformation($"Succedded executed command {_inner.GetType().FullName}"); | |||||
return response; | |||||
} | |||||
} | |||||
} |
@ -1,19 +0,0 @@ | |||||
<?xml version="1.0" encoding="utf-8"?> | |||||
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> | |||||
<PropertyGroup> | |||||
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0</VisualStudioVersion> | |||||
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath> | |||||
</PropertyGroup> | |||||
<Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.Props" Condition="'$(VSToolsPath)' != ''" /> | |||||
<PropertyGroup Label="Globals"> | |||||
<ProjectGuid>4193caa3-a1c3-4818-a06f-a2d85fde77e7</ProjectGuid> | |||||
<RootNamespace>Microsoft.eShopOnContainers.Services.Ordering.Application</RootNamespace> | |||||
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">.\obj</BaseIntermediateOutputPath> | |||||
<OutputPath Condition="'$(OutputPath)'=='' ">.\bin\</OutputPath> | |||||
<TargetFrameworkVersion>v4.5.1</TargetFrameworkVersion> | |||||
</PropertyGroup> | |||||
<PropertyGroup> | |||||
<SchemaVersion>2.0</SchemaVersion> | |||||
</PropertyGroup> | |||||
<Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.targets" Condition="'$(VSToolsPath)' != ''" /> | |||||
</Project> |
@ -1,19 +0,0 @@ | |||||
using System.Reflection; | |||||
using System.Runtime.CompilerServices; | |||||
using System.Runtime.InteropServices; | |||||
// General Information about an assembly is controlled through the following | |||||
// set of attributes. Change these attribute values to modify the information | |||||
// associated with an assembly. | |||||
[assembly: AssemblyConfiguration("")] | |||||
[assembly: AssemblyCompany("")] | |||||
[assembly: AssemblyProduct("Ordering.Application")] | |||||
[assembly: AssemblyTrademark("")] | |||||
// Setting ComVisible to false makes the types in this assembly not visible | |||||
// to COM components. If you need to access a type in this assembly from | |||||
// COM, set the ComVisible attribute to true on that type. | |||||
[assembly: ComVisible(false)] | |||||
// The following GUID is for the ID of the typelib if this project is exposed to COM | |||||
[assembly: Guid("4193caa3-a1c3-4818-a06f-a2d85fde77e7")] |
@ -1,13 +0,0 @@ | |||||
namespace Microsoft.eShopOnContainers.Services.Ordering.Application.Queries | |||||
{ | |||||
using System.Threading.Tasks; | |||||
public interface IOrderQueries | |||||
{ | |||||
Task<dynamic> GetOrder(int id); | |||||
Task<dynamic> GetOrders(); | |||||
Task<dynamic> GetCardTypes(); | |||||
} | |||||
} |
@ -1,128 +0,0 @@ | |||||
namespace Microsoft.eShopOnContainers.Services.Ordering.Application.Queries | |||||
{ | |||||
using Dapper; | |||||
using Microsoft.Extensions.Configuration; | |||||
using System.Data.SqlClient; | |||||
using System.Threading.Tasks; | |||||
using System; | |||||
using System.Dynamic; | |||||
using System.Collections.Generic; | |||||
using System.Linq; | |||||
public class OrderQueries | |||||
: IOrderQueries | |||||
{ | |||||
private string _connectionString = string.Empty; | |||||
public OrderQueries(IConfiguration configuration) | |||||
{ | |||||
_connectionString = configuration["ConnectionString"]; | |||||
} | |||||
public async Task<dynamic> GetOrder(int id) | |||||
{ | |||||
using (var connection = new SqlConnection(_connectionString)) | |||||
{ | |||||
connection.Open(); | |||||
var result = await connection.QueryAsync<dynamic>( | |||||
@"select o.[Id] as ordernumber,o.OrderDate as date, os.Name as status, | |||||
oi.ProductName as productname, oi.Units as units, oi.UnitPrice as unitprice, oi.PictureUrl as pictureurl, | |||||
oa.Street as street, oa.City as city, oa.Country as country, oa.State as state, oa.ZipCode as zipcode | |||||
FROM ordering.Orders o | |||||
LEFT JOIN ordering.Orderitems oi ON o.Id = oi.orderid | |||||
LEFT JOIN ordering.orderstatus os on o.StatusId = os.Id | |||||
LEFT JOIN ordering.address oa on o.ShippingAddressId = oa.Id | |||||
WHERE o.Id=@id" | |||||
, new { id } | |||||
); | |||||
if (result.AsList().Count == 0) | |||||
throw new KeyNotFoundException(); | |||||
return MapOrderItems(result); | |||||
} | |||||
} | |||||
public async Task<dynamic> GetOrders() | |||||
{ | |||||
using (var connection = new SqlConnection(_connectionString)) | |||||
{ | |||||
connection.Open(); | |||||
return await connection.QueryAsync<dynamic>(@"SELECT o.[Id] as ordernumber,o.[OrderDate] as [date],os.[Name] as [status],SUM(oi.units*oi.unitprice) as total | |||||
FROM [ordering].[Orders] o | |||||
LEFT JOIN[ordering].[orderitems] oi ON o.Id = oi.orderid | |||||
LEFT JOIN[ordering].[orderstatus] os on o.StatusId = os.Id | |||||
GROUP BY o.[Id], o.[OrderDate], os.[Name]"); | |||||
} | |||||
} | |||||
public async Task<dynamic> GetCardTypes() | |||||
{ | |||||
using (var connection = new SqlConnection(_connectionString)) | |||||
{ | |||||
connection.Open(); | |||||
return await connection.QueryAsync<dynamic>("SELECT * FROM ordering.cardtypes"); | |||||
} | |||||
} | |||||
private dynamic MapOrderItems(dynamic result) | |||||
{ | |||||
dynamic order = new ExpandoObject(); | |||||
order.ordernumber = result[0].ordernumber; | |||||
order.date = result[0].date; | |||||
order.status = result[0].status; | |||||
order.street = result[0].street; | |||||
order.city = result[0].city; | |||||
order.zipcode = result[0].zipcode; | |||||
order.country = result[0].country; | |||||
order.orderitems = new List<dynamic>(); | |||||
order.total = 0; | |||||
foreach (dynamic item in result) | |||||
{ | |||||
dynamic orderitem = new ExpandoObject(); | |||||
orderitem.productname = item.productname; | |||||
orderitem.units = item.units; | |||||
orderitem.unitprice = item.unitprice; | |||||
orderitem.pictureurl = item.pictureurl; | |||||
order.total += item.units * item.unitprice; | |||||
order.orderitems.Add(orderitem); | |||||
} | |||||
return order; | |||||
} | |||||
//TODO/CCE: try to use this method instead actual. | |||||
//private object MapOrderItems(dynamic result) | |||||
//{ | |||||
// IEnumerable<dynamic> items = (result as System.Collections.IEnumerable).Cast<dynamic>(); | |||||
// var order = new | |||||
// { | |||||
// ordernumber = result[0].ordernumbe, | |||||
// date = result[0].date, | |||||
// status = result[0].status, | |||||
// street = result[0].street, | |||||
// city = result[0].city, | |||||
// zipcode = result[0].zipcode, | |||||
// country = result[0].country, | |||||
// total = items.Select(r => (int)r.units * (int)r.unitprice).Sum(), | |||||
// orderItems = items.Select(r => new | |||||
// { | |||||
// productname = r.productname, | |||||
// units = r.units, | |||||
// unitprice = r.unitprice, | |||||
// pictureurl = r.pictureurl | |||||
// }) | |||||
// }; | |||||
// return order; | |||||
//} | |||||
} | |||||
} |
@ -1,21 +0,0 @@ | |||||
{ | |||||
"version": "1.0.0-*", | |||||
"dependencies": { | |||||
"NETStandard.Library": "1.6.0", | |||||
"MediatR": "2.1.0", | |||||
"Dapper": "1.50.2", | |||||
"System.Dynamic.Runtime": "4.0.11", | |||||
"Microsoft.CSharp": "4.0.1", | |||||
"Microsoft.Extensions.Configuration": "1.0.0", | |||||
"System.Data.SqlClient": "4.1.0", | |||||
"Microsoft.Extensions.Logging.Abstractions": "1.0.0", | |||||
"Ordering.Domain": "1.0.0-*" | |||||
}, | |||||
"frameworks": { | |||||
"netstandard1.6": { | |||||
"imports": "dnxcore50" | |||||
} | |||||
} | |||||
} |
@ -0,0 +1,111 @@ | |||||
rules: | |||||
# https://github.com/sasstools/sass-lint/tree/master/docs/rules | |||||
# 0 = disabled - 1 = warning - 2 = error | |||||
# Extends | |||||
extends-before-mixins: 1 | |||||
extends-before-declarations: 2 | |||||
placeholder-in-extend: 0 | |||||
# Mixins | |||||
mixins-before-declarations: 2 | |||||
# Line Spacing | |||||
one-declaration-per-line: 2 | |||||
empty-line-between-blocks: 2 | |||||
single-line-per-selector: 2 | |||||
# Disallows | |||||
# We disable some of that because we know that | |||||
# if you use it is because is necessary | |||||
no-attribute-selectors: 0 | |||||
no-color-hex: 0 | |||||
no-color-keywords: 2 | |||||
no-color-literals: 0 | |||||
no-combinators: 0 | |||||
no-css-comments: 0 | |||||
no-debug: 1 | |||||
no-disallowed-properties: 0 | |||||
no-duplicate-properties: 2 | |||||
no-empty-rulesets: 1 | |||||
no-extends: 0 | |||||
no-ids: 2 | |||||
no-important: 0 | |||||
no-invalid-hex: 2 | |||||
no-mergeable-selectors: 1 | |||||
no-misspelled-properties: 2 | |||||
no-qualifying-elements: 0 | |||||
no-trailing-whitespace: 2 | |||||
no-trailing-zero: 2 | |||||
no-transition-all: 0 | |||||
no-universal-selectors: 0 | |||||
no-url-domains: 0 | |||||
no-url-protocols: 0 | |||||
no-vendor-prefixes: 2 | |||||
no-warn: 2 | |||||
property-units: 0 | |||||
# Nesting | |||||
declarations-before-nesting: 2 | |||||
force-attribute-nesting: 0 | |||||
force-element-nesting: 0 | |||||
force-pseudo-nesting: 0 | |||||
# Name Formats | |||||
class-name-format: 0 | |||||
function-name-format: 0 | |||||
id-name-format: 0 | |||||
mixin-name-format: 0 | |||||
placeholder-name-format: | |||||
- 1 | |||||
- allow-leading-underscore: true | |||||
- convention: hyphenatedlowercase | |||||
variable-name-format: | |||||
- 1 | |||||
- allow-leading-underscore: true | |||||
- convention: hyphenatedlowercase | |||||
# Style Guide | |||||
attribute-quotes: 2 | |||||
# We know that always 1 level | |||||
bem-depth: 0 | |||||
border-zero: 2 | |||||
brace-style: | |||||
- 2 | |||||
- style: 1tbs | |||||
clean-import-paths: 2 | |||||
empty-args: 2 | |||||
hex-length: | |||||
- 2 | |||||
- style: long | |||||
hex-notation: | |||||
- 2 | |||||
- style: uppercase | |||||
indentation: | |||||
- 2 | |||||
- size: 4 | |||||
leading-zero: 2 | |||||
max-line-length: 0 | |||||
max-file-line-count: 0 | |||||
nesting-depth: 0 | |||||
# alphabetically | |||||
property-sort-order: 2 | |||||
pseudo-element: 0 | |||||
quotes: 2 | |||||
shorthand-values: 0 | |||||
url-quotes: 0 | |||||
variable-for-property: 0 | |||||
zero-unit: 2 | |||||
# Inner Spacing | |||||
space-after-comma: 2 | |||||
space-before-colon: 2 | |||||
space-after-colon: 2 | |||||
space-before-brace: 2 | |||||
space-before-bang: 2 | |||||
space-after-bang: 2 | |||||
space-between-parens: 2 | |||||
space-around-operator: 2 | |||||
# Final Items | |||||
trailing-semicolon: 2 | |||||
final-newline: 2 |
@ -0,0 +1,7 @@ | |||||
<div class="esh-header"> | |||||
<div class="container"> | |||||
<a class="esh-header-back" routerLink="{{url}}"> | |||||
<ng-content></ng-content> | |||||
</a> | |||||
</div> | |||||
</div> |
@ -0,0 +1,21 @@ | |||||
@import "../../../variables"; | |||||
.esh-header { | |||||
$header-height: 4rem; | |||||
background-color: $color-brand; | |||||
height: $header-height; | |||||
&-back { | |||||
color: rgba($color-foreground-brighter, .5); | |||||
line-height: $header-height; | |||||
text-transform: uppercase; | |||||
text-decoration: none; | |||||
transition: color $animation-speed-default; | |||||
&:hover { | |||||
color: $color-foreground-brighter; | |||||
transition: color $animation-speed-default; | |||||
} | |||||
} | |||||
} |
@ -0,0 +1,11 @@ | |||||
import { Component, Input } from '@angular/core'; | |||||
@Component({ | |||||
selector: 'esh-header', | |||||
templateUrl: './header.html', | |||||
styleUrls: ['./header.scss'] | |||||
}) | |||||
export class Header { | |||||
@Input() | |||||
url: string; | |||||
} |
@ -1,8 +1,35 @@ | |||||
<button *ngIf="!authenticated" class="identity-login" (click)="login()">Login</button> | |||||
<div *ngIf="authenticated" class="identity-user"> | |||||
<div><span>{{userName}}</span></div><div style="float: right;top: 0;right: -15px;position: absolute;"><img src="../../../../images/arrow-down.png" class="identity-downArrow"></div> | |||||
<div class="identity-userDropdown"> | |||||
<div [routerLink]="['orders']">MY ORDERS<img src="../../../../images/my_orders.png"></div> | |||||
<div (click)="logoutClicked($event)">LOG OUT<img src="../../../../images/logout.png"></div> | |||||
</div> | |||||
<div class="esh-identity"> | |||||
<section class="esh-identity-section" | |||||
*ngIf="!authenticated"> | |||||
<div class="esh-identity-item" | |||||
(click)="login()"> | |||||
<div class="esh-identity-name esh-identity-name--upper">Login</div> | |||||
</div> | |||||
</section> | |||||
<section class="esh-identity-section" | |||||
*ngIf="authenticated"> | |||||
<div class="esh-identity-name">{{userName}}</div> | |||||
<img class="esh-identity-image" src="../../../../images/arrow-down.png"> | |||||
</section> | |||||
<section class="esh-identity-drop" | |||||
*ngIf="authenticated"> | |||||
<div class="esh-identity-item" | |||||
[routerLink]="['orders']"> | |||||
<div class="esh-identity-name esh-identity-name--upper">My orders</div> | |||||
<img class="esh-identity-image" src="../../../../images/my_orders.png"> | |||||
</div> | |||||
<div class="esh-identity-item" | |||||
(click)="logoutClicked($event)"> | |||||
<div class="esh-identity-name esh-identity-name--upper">Log Out</div> | |||||
<img class="esh-identity-image" src="../../../../images/logout.png"> | |||||
</div> | |||||
</section> | |||||
</div> | </div> |
@ -1,63 +1,56 @@ | |||||
.identity { | |||||
&-user { | |||||
position: absolute !important; | |||||
top: 30px; | |||||
right: 120px; | |||||
cursor: pointer; | |||||
@import "../../../variables"; | |||||
&:hover .identity-userDropdown { | |||||
display: block; | |||||
} | |||||
} | |||||
.esh-identity { | |||||
line-height: 3rem; | |||||
position: relative; | |||||
text-align: right; | |||||
&-userDropdown { | |||||
display: none; | |||||
position: absolute; | |||||
background-color: #FFFFFF; | |||||
min-width: 160px; | |||||
box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2); | |||||
right: -15px; | |||||
z-index: 3; | |||||
&-section { | |||||
display: inline-block; | |||||
width: 100%; | |||||
} | |||||
&:hover { | |||||
display: block; | |||||
} | |||||
&-name { | |||||
display: inline-block; | |||||
& div { | |||||
color: black; | |||||
padding: 12px 16px; | |||||
text-decoration: none; | |||||
display: block; | |||||
text-align: right; | |||||
&--upper { | |||||
text-transform: uppercase; | text-transform: uppercase; | ||||
} | |||||
&:hover { | |||||
color: #83d01b; | |||||
} | |||||
@media screen and (max-width: $media-screen-s) { | |||||
font-size: $font-size-s; | |||||
} | } | ||||
} | } | ||||
&-downArrow { | |||||
height: 7px; | |||||
width: 10px; | |||||
&-image { | |||||
display: inline-block; | display: inline-block; | ||||
margin-left: 20px; | |||||
} | |||||
&:hover > identity.userDropdown { | |||||
display: block; | |||||
} | |||||
&-drop { | |||||
background: $color-background-brighter; | |||||
height: 0; | |||||
min-width: 14rem; | |||||
right: 0; | |||||
overflow: hidden; | |||||
padding: .5rem; | |||||
position: absolute; | |||||
top: 2.5rem; | |||||
transition: height $animation-speed-default; | |||||
} | |||||
&:hover &-drop { | |||||
border: $border-light solid $color-foreground-bright; | |||||
height: 7rem; | |||||
transition: height $animation-speed-default; | |||||
} | } | ||||
&-login { | |||||
border: 1px solid #00a69c; | |||||
height: 36px !important; | |||||
margin-right: 10px; | |||||
margin-top: 10px; | |||||
background-color: #fff; | |||||
color: #00a69c; | |||||
text-transform: uppercase; | |||||
max-width: 140px; | |||||
width: 140px; | |||||
padding-top: 8px !important; | |||||
&-item { | |||||
cursor: pointer; | |||||
transition: color $animation-speed-default; | |||||
&:hover { | |||||
color: $color-secondary-dark; | |||||
transition: color $animation-speed-default; | |||||
} | |||||
} | } | ||||
} | } |
@ -1,178 +0,0 @@ | |||||
{ | |||||
"rulesDirectory": [ | |||||
"node_modules/codelyzer" | |||||
], | |||||
"rules": { | |||||
"directive-selector-name": [ | |||||
true, | |||||
"camelCase" | |||||
], | |||||
"component-selector-name": [ | |||||
true, | |||||
"kebab-case" | |||||
], | |||||
"directive-selector-type": [ | |||||
true, | |||||
"attribute" | |||||
], | |||||
"component-selector-type": [ | |||||
true, | |||||
"element" | |||||
], | |||||
"directive-selector-prefix": [ | |||||
true, | |||||
"appd" | |||||
], | |||||
"component-selector-prefix": [ | |||||
true, | |||||
"appc" | |||||
], | |||||
"use-input-property-decorator": true, | |||||
"use-output-property-decorator": true, | |||||
"use-host-property-decorator": true, | |||||
"no-attribute-parameter-decorator": true, | |||||
"no-input-rename": true, | |||||
"no-output-rename": true, | |||||
"no-forward-ref": true, | |||||
"use-life-cycle-interface": true, | |||||
"use-pipe-transform-interface": true, | |||||
"pipe-naming": [ | |||||
true, | |||||
"camelCase", | |||||
"appf" | |||||
], | |||||
"component-class-suffix": true, | |||||
"directive-class-suffix": true, | |||||
"import-destructuring-spacing": true, | |||||
"member-access": false, | |||||
"member-ordering": [ | |||||
true, | |||||
"public-before-private", | |||||
"static-before-instance", | |||||
"variables-before-functions" | |||||
], | |||||
"no-any": false, | |||||
"no-inferrable-types": false, | |||||
"no-internal-module": true, | |||||
"no-var-requires": false, | |||||
"typedef": false, | |||||
"typedef-whitespace": [ | |||||
true, | |||||
{ | |||||
"call-signature": "nospace", | |||||
"index-signature": "nospace", | |||||
"parameter": "nospace", | |||||
"property-declaration": "nospace", | |||||
"variable-declaration": "nospace" | |||||
}, | |||||
{ | |||||
"call-signature": "space", | |||||
"index-signature": "space", | |||||
"parameter": "space", | |||||
"property-declaration": "space", | |||||
"variable-declaration": "space" | |||||
} | |||||
], | |||||
"ban": false, | |||||
"curly": false, | |||||
"forin": true, | |||||
"label-position": true, | |||||
"label-undefined": true, | |||||
"no-arg": true, | |||||
"no-bitwise": true, | |||||
"no-conditional-assignment": true, | |||||
"no-console": [ | |||||
true, | |||||
"debug", | |||||
"info", | |||||
"time", | |||||
"timeEnd", | |||||
"trace" | |||||
], | |||||
"no-construct": true, | |||||
"no-debugger": true, | |||||
"no-duplicate-key": true, | |||||
"no-duplicate-variable": true, | |||||
"no-empty": false, | |||||
"no-eval": true, | |||||
"no-null-keyword": true, | |||||
"no-shadowed-variable": true, | |||||
"no-string-literal": true, | |||||
"no-switch-case-fall-through": true, | |||||
"no-unreachable": true, | |||||
"no-unused-expression": true, | |||||
"no-unused-variable": false, | |||||
"no-use-before-declare": true, | |||||
"no-var-keyword": true, | |||||
"radix": true, | |||||
"switch-default": true, | |||||
"triple-equals": [ | |||||
true, | |||||
"allow-null-check" | |||||
], | |||||
"use-strict": [ | |||||
true, | |||||
"check-module" | |||||
], | |||||
"eofline": true, | |||||
"indent": [ | |||||
true, | |||||
"spaces" | |||||
], | |||||
"max-line-length": [ | |||||
true, | |||||
200 | |||||
], | |||||
"no-require-imports": false, | |||||
"no-trailing-whitespace": true, | |||||
"object-literal-sort-keys": false, | |||||
"trailing-comma": [ | |||||
true, | |||||
{ | |||||
"multiline": "never", | |||||
"singleline": "never" | |||||
} | |||||
], | |||||
"align": false, | |||||
"class-name": true, | |||||
"comment-format": [ | |||||
true, | |||||
"check-space" | |||||
], | |||||
"interface-name": false, | |||||
"jsdoc-format": true, | |||||
"no-consecutive-blank-lines": false, | |||||
"no-constructor-vars": false, | |||||
"one-line": [ | |||||
true, | |||||
"check-open-brace", | |||||
"check-catch", | |||||
"check-else", | |||||
"check-finally", | |||||
"check-whitespace" | |||||
], | |||||
"quotemark": [ | |||||
true, | |||||
"single", | |||||
"avoid-escape" | |||||
], | |||||
"semicolon": [ | |||||
true, | |||||
"always" | |||||
], | |||||
"variable-name": [ | |||||
true, | |||||
"check-format", | |||||
"allow-leading-underscore", | |||||
"ban-keywords" | |||||
], | |||||
"whitespace": [ | |||||
true, | |||||
"check-branch", | |||||
"check-decl", | |||||
"check-operator", | |||||
"check-separator", | |||||
"check-type" | |||||
] | |||||
} | |||||
} |
@ -0,0 +1,63 @@ | |||||
| |||||
//namespace FunctionalTests.Services.Basket | |||||
//{ | |||||
// using Microsoft.eShopOnContainers.Services.Basket.API; | |||||
// using Microsoft.eShopOnContainers.Services.Basket.API.Model; | |||||
// using Microsoft.Extensions.Logging; | |||||
// using Microsoft.Extensions.Options; | |||||
// using System.Collections.Generic; | |||||
// using System.Threading.Tasks; | |||||
// using Xunit; | |||||
// public class RedisBasketRepositoryTests | |||||
// { | |||||
// [Fact] | |||||
// public async Task UpdateBasket_return_and_add_basket() | |||||
// { | |||||
// var redisBasketRepository = BuildBasketRepository(); | |||||
// var basket = await redisBasketRepository.UpdateBasket(new CustomerBasket("customerId") | |||||
// { | |||||
// BuyerId = "buyerId", | |||||
// Items = BuildBasketItems() | |||||
// }); | |||||
// Assert.NotNull(basket); | |||||
// Assert.Equal(1, basket.Items.Count); | |||||
// } | |||||
// [Fact] | |||||
// public async Task GetBasket_return_existing_basket() | |||||
// { | |||||
// } | |||||
// RedisBasketRepository BuildBasketRepository() | |||||
// { | |||||
// var loggerFactory = new LoggerFactory(); | |||||
// var options = Options.Create<BasketSettings>(new BasketSettings() | |||||
// { | |||||
// ConnectionString = "127.0.0.1" | |||||
// }); | |||||
// return new RedisBasketRepository(options, loggerFactory); | |||||
// } | |||||
// List<BasketItem> BuildBasketItems() | |||||
// { | |||||
// return new List<BasketItem>() | |||||
// { | |||||
// new BasketItem() | |||||
// { | |||||
// Id = "basketId", | |||||
// PictureUrl = "pictureurl", | |||||
// ProductId = "productId", | |||||
// ProductName = "productName", | |||||
// Quantity = 1, | |||||
// UnitPrice = 1 | |||||
// } | |||||
// }; | |||||
// } | |||||
// } | |||||
//} |
@ -1,136 +0,0 @@ | |||||
using System; | |||||
using Xunit; | |||||
using System.Threading.Tasks; | |||||
using Moq; | |||||
using MediatR; | |||||
using Microsoft.eShopOnContainers.Services.Ordering.API.Controllers; | |||||
using Microsoft.eShopOnContainers.Services.Ordering.Api.Application.Commands; | |||||
using Microsoft.AspNetCore.Mvc; | |||||
using Microsoft.eShopOnContainers.Services.Ordering.API.Infrastructure.Services; | |||||
using Microsoft.eShopOnContainers.Services.Ordering.Api.Application.Queries; | |||||
using System.Collections.Generic; | |||||
namespace UnitTest.Ordering.Controllers | |||||
{ | |||||
public class OrderControllerTest | |||||
{ | |||||
private readonly Mock<IMediator> _mediatorMock; | |||||
private readonly Mock<IIdentityService> _identityMock; | |||||
private readonly Mock<IOrderQueries> _queriesMock; | |||||
private readonly string _userIdentity; | |||||
public OrderControllerTest() | |||||
{ | |||||
//Mocks; | |||||
_mediatorMock = new Mock<IMediator>(); | |||||
_identityMock = new Mock<IIdentityService>(); | |||||
_queriesMock = new Mock<IOrderQueries>(); | |||||
_userIdentity = Guid.NewGuid().ToString(); | |||||
} | |||||
[Fact] | |||||
public async Task AddOrder_ReturnsBadRequestResult_WhenPersitenceOperationFails() | |||||
{ | |||||
// Arrange | |||||
var orderRequest = new object() as IAsyncRequest<bool>; | |||||
_mediatorMock.Setup(mediator => mediator.SendAsync(OrderFakeNotExpired())) | |||||
.Returns(Task.FromResult(false)); | |||||
_identityMock.Setup(identity => identity.GetUserIdentity()) | |||||
.Returns(Guid.NewGuid().ToString()); | |||||
var controller = new OrdersController(_mediatorMock.Object, _queriesMock.Object, _identityMock.Object); | |||||
// Act | |||||
var badRequestResult = await controller.AddOrder(OrderFakeNotExpired()); | |||||
// Assert | |||||
Assert.IsType<BadRequestResult>(badRequestResult); | |||||
} | |||||
[Fact] | |||||
public async Task GetOrder_ReturnsNotFound_WhenItemNotFound() | |||||
{ | |||||
// Arrange | |||||
_queriesMock.Setup(queries => queries.GetOrder(1)) | |||||
.Throws(new KeyNotFoundException()); | |||||
var controller = new OrdersController(_mediatorMock.Object, _queriesMock.Object, _identityMock.Object); | |||||
// Act | |||||
var notFoundResult = await controller.GetOrder(1); | |||||
// Assert | |||||
Assert.IsType<NotFoundResult>(notFoundResult); | |||||
} | |||||
[Fact] | |||||
public async Task GetOrder_ReturnsOkObjecResult_WheItemFound() | |||||
{ | |||||
// Arrange | |||||
_queriesMock.Setup(queries => queries.GetOrder(1)) | |||||
.Returns(Task.FromResult(new object())); | |||||
var controller = new OrdersController(_mediatorMock.Object, _queriesMock.Object, _identityMock.Object); | |||||
// Act | |||||
var OkObjectResult = await controller.GetOrder(1); | |||||
// Assert | |||||
Assert.IsType<OkObjectResult>(OkObjectResult); | |||||
} | |||||
[Fact] | |||||
public async Task GetOrders_ReturnsOkObjectResult() | |||||
{ | |||||
// Arrange | |||||
_queriesMock.Setup(queries => queries.GetOrders()) | |||||
.Returns(Task.FromResult(new object())); | |||||
var controller = new OrdersController(_mediatorMock.Object, _queriesMock.Object, _identityMock.Object); | |||||
// Act | |||||
var OkObjectResult = await controller.GetOrders(); | |||||
// Assert | |||||
Assert.IsType<OkObjectResult>(OkObjectResult); | |||||
} | |||||
[Fact] | |||||
public async Task GetCardTypes() | |||||
{ | |||||
// Arrange | |||||
_queriesMock.Setup(queries => queries.GetCardTypes()) | |||||
.Returns(Task.FromResult(new object())); | |||||
var controller = new OrdersController(_mediatorMock.Object, _queriesMock.Object, _identityMock.Object); | |||||
// Act | |||||
var OkObjectResult = await controller.GetCardTypes(); | |||||
// Assert | |||||
Assert.IsType<OkObjectResult>(OkObjectResult); | |||||
} | |||||
//Fakes | |||||
private NewOrderRequest OrderFakeNotExpired() | |||||
{ | |||||
return new NewOrderRequest() | |||||
{ | |||||
CardTypeId = 1, | |||||
CardExpiration = new DateTime(2020, 12, 12), | |||||
Buyer = _userIdentity | |||||
}; | |||||
} | |||||
private NewOrderRequest OrderFakeExpired() | |||||
{ | |||||
return new NewOrderRequest() | |||||
{ | |||||
CardTypeId = 1, | |||||
CardExpiration = DateTime.Now.AddYears(-1) | |||||
}; | |||||
} | |||||
} | |||||
} |