Skip to content

Commit 5f5dd7f

Browse files
authored
feat: make homework for jest (#14)
1 parent afa8f9c commit 5f5dd7f

File tree

9 files changed

+253
-2
lines changed

9 files changed

+253
-2
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
"scripts": {
88
"start": "webpack serve --mode development",
99
"build": "webpack --mode production",
10-
"test": "jest src",
10+
"test": "jest src/feature",
1111
"lint": "eslint src --fix",
1212
"storybook": "storybook dev -p 6006",
1313
"build-storybook": "storybook build",

src/app/App.tsx

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { BrowserRouter, Route, RouteProps, Routes } from 'react-router';
44
import { useTranslation } from 'react-i18next';
55
import './tailwind.css';
66
import { Layout } from '../entities';
7-
import { Store, StoreBasket, StoreCard, StoreList } from '../pages';
7+
import { AccountServicePage, Store, StoreBasket, StoreCard, StoreList } from '../pages';
88
import { defaultContext, ELangVariables, EThemeVariables, IStoreContext, StoreContext } from './StoreContext';
99

1010
function App() {
@@ -26,6 +26,10 @@ function App() {
2626
path: '/list',
2727
element: <StoreList />,
2828
},
29+
{
30+
path: '/account-service',
31+
element: <AccountServicePage />,
32+
},
2933
];
3034
const { theme, lang } = contextValue;
3135
const { i18n, t } = useTranslation();
@@ -66,6 +70,10 @@ function App() {
6670
path: '/list',
6771
text: t('tempLinks.toList'),
6872
},
73+
{
74+
path: '/account-service',
75+
text: t('tempLinks.toAccountService'),
76+
},
6977
];
7078
const currentUrl = window.location.pathname;
7179
// END TODO

src/app/i18n/translation.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ export const resources = {
77
toCard: 'to Card',
88
toBasket: 'to Basket',
99
toList: 'to Goods List',
10+
toAccountService: 'to Account Service',
1011
},
1112
card: {
1213
stockStatus: {
@@ -84,6 +85,13 @@ export const resources = {
8485
submitAuth: 'Log in',
8586
},
8687
},
88+
accountServicePage: {
89+
userDiscount: 'Discount for premium user',
90+
userProductDiscount: 'A discount for a premium user on a car:',
91+
commonDiscount: 'The final discount for a premium user to purchase a car:',
92+
initialPrice: 'The initial price for the car:',
93+
finalPrice: 'The final price for a premium user for a car:',
94+
},
8795
},
8896
},
8997
ru: {
@@ -94,6 +102,7 @@ export const resources = {
94102
toCard: 'В карточку',
95103
toBasket: 'В корзину',
96104
toList: 'К списку товаров',
105+
toAccountService: 'К сервису для Аккаунта',
97106
},
98107
card: {
99108
stockStatus: {
@@ -171,6 +180,13 @@ export const resources = {
171180
submitAuth: 'Войти',
172181
},
173182
},
183+
accountServicePage: {
184+
userDiscount: 'Скидка для премиум-пользователя',
185+
userProductDiscount: 'Скидка для премиум-пользователя на машину:',
186+
commonDiscount: 'Итоговая скидка для премиум-пользователя на покупку машины:',
187+
initialPrice: 'Начальная цена за машину:',
188+
finalPrice: 'Итоговая цена для премиум-пользователя на машину:',
189+
},
174190
},
175191
},
176192
};
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
import AccountService from './AccountService';
2+
import { UserType, ProductType } from './interfaces';
3+
4+
describe(`Сервис предоставления скидок: \n`, () => {
5+
let service: AccountService;
6+
7+
beforeEach(() => {
8+
service = new AccountService();
9+
});
10+
11+
describe('Скидка за тип аккаунта', () => {
12+
it('Standard (0%)', () => {
13+
const userType = UserType.Standard;
14+
const discount = service.getDiscount(userType);
15+
expect(discount).toBe(0);
16+
});
17+
it('Premium (10%)', () => {
18+
const userType = UserType.Premium;
19+
const discount = service.getDiscount(userType);
20+
expect(discount).toBe(0.1);
21+
});
22+
it('Gold (20%)', () => {
23+
const userType = UserType.Gold;
24+
const discount = service.getDiscount(userType);
25+
expect(discount).toBe(0.2);
26+
});
27+
it('Free (50%)', () => {
28+
const userType = UserType.Free;
29+
const discount = service.getDiscount(userType);
30+
expect(discount).toBe(0.3);
31+
});
32+
});
33+
34+
describe('Скидка для Gold юзеров за товар', () => {
35+
const userType = UserType.Gold;
36+
37+
it('Car (30%)', () => {
38+
const discount = service.getCommonDiscount(userType, ProductType.Car);
39+
expect(discount).toBe(30);
40+
});
41+
it('Toy (24%)', () => {
42+
const discount = service.getCommonDiscount(userType, ProductType.Toy);
43+
expect(discount).toBe(24);
44+
});
45+
it('Food (40%)', () => {
46+
const discount = service.getCommonDiscount(userType, ProductType.Food);
47+
expect(discount).toBe(40);
48+
});
49+
});
50+
51+
describe('Стоимость товара Car (5.000.000) для юзеров', () => {
52+
const initialPrice = 5000000;
53+
const carProduct = ProductType.Car;
54+
55+
it('Standart (5000000)', () => {
56+
const userType = UserType.Standard;
57+
const discount = service.calculateFinalPrice(initialPrice, userType, carProduct);
58+
expect(discount).toBe(5000000);
59+
});
60+
it('Premium (4250000)', () => {
61+
const userType = UserType.Premium;
62+
const discount = service.calculateFinalPrice(initialPrice, userType, carProduct);
63+
expect(discount).toBe(4250000);
64+
});
65+
it('Gold (3500000)', () => {
66+
const userType = UserType.Gold;
67+
const discount = service.calculateFinalPrice(initialPrice, userType, carProduct);
68+
expect(discount).toBe(3500000);
69+
});
70+
it('Free (2500000)', () => {
71+
const userType = UserType.Free;
72+
const discount = service.calculateFinalPrice(initialPrice, userType, carProduct);
73+
expect(discount).toBe(2500000);
74+
});
75+
});
76+
});
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
import { UserType, ProductType } from './interfaces';
2+
3+
class AccountService {
4+
private userDiscounts: { userType: UserType; discount: number }[];
5+
private productsList: { id: number; title: ProductType }[];
6+
private userProductsDiscount: { userType: UserType; productId: number; discount: number }[];
7+
8+
constructor() {
9+
this.userDiscounts = [
10+
{ userType: UserType.Standard, discount: 0 },
11+
{ userType: UserType.Premium, discount: 0.1 },
12+
{ userType: UserType.Gold, discount: 0.2 },
13+
{ userType: UserType.Free, discount: 0.3 },
14+
];
15+
this.productsList = [
16+
{ id: 1, title: ProductType.Car },
17+
{ id: 2, title: ProductType.Food },
18+
{ id: 3, title: ProductType.Toy },
19+
];
20+
this.userProductsDiscount = [
21+
{ userType: UserType.Standard, productId: 1, discount: 0 },
22+
{ userType: UserType.Standard, productId: 2, discount: 0 },
23+
{ userType: UserType.Standard, productId: 3, discount: 0 },
24+
{ userType: UserType.Premium, productId: 1, discount: 0.05 },
25+
{ userType: UserType.Premium, productId: 2, discount: 0.1 },
26+
{ userType: UserType.Premium, productId: 3, discount: 0.02 },
27+
{ userType: UserType.Gold, productId: 1, discount: 0.1 },
28+
{ userType: UserType.Gold, productId: 2, discount: 0.2 },
29+
{ userType: UserType.Gold, productId: 3, discount: 0.04 },
30+
{ userType: UserType.Free, productId: 1, discount: 0.2 },
31+
{ userType: UserType.Free, productId: 2, discount: 0.3 },
32+
{ userType: UserType.Free, productId: 3, discount: 0.12 },
33+
];
34+
}
35+
36+
// Метод получения списка скидок по статусам профилей
37+
public getUserDiscounts() {
38+
return new Promise((resolve) => {
39+
setTimeout(() => {
40+
resolve(this.userDiscounts);
41+
}, 1000);
42+
});
43+
}
44+
// Метод получения списка товаров
45+
public getProductsList() {
46+
return new Promise((resolve) => {
47+
setTimeout(() => {
48+
resolve(this.productsList);
49+
}, 1000);
50+
});
51+
}
52+
// Метод получения скидок на определенный товар по типам профилей
53+
public getUserProductsDiscountList() {
54+
return new Promise((resolve) => {
55+
setTimeout(() => {
56+
resolve(this.userProductsDiscount);
57+
}, 1000);
58+
});
59+
}
60+
61+
// Метод получения id товара по названию
62+
public getProductId(productTitle: ProductType): number {
63+
const productId = this.productsList.find((id) => id.title === productTitle);
64+
return productId?.id;
65+
}
66+
67+
// Метод получения скидки для пользователя по статусам
68+
public getDiscount(userType: UserType): number {
69+
const userDiscount = this.userDiscounts.find((discount) => discount.userType === userType);
70+
return userDiscount?.discount;
71+
}
72+
// Метод получения скидки на определенный товар для конкретного статуса
73+
public getUserProductDiscount(userType: UserType, productTitle: ProductType): number {
74+
const discountItem = this.userProductsDiscount.find(
75+
(item) => item.userType === userType && item.productId === this.getProductId(productTitle)
76+
);
77+
return discountItem?.discount;
78+
}
79+
// Метод формирования общей скидки (скидки суммируются)
80+
public getCommonDiscount(userType: UserType, productTitle: ProductType): number {
81+
const commonDiscount = this.getDiscount(userType) * 100 + this.getUserProductDiscount(userType, productTitle) * 100;
82+
return commonDiscount;
83+
}
84+
// Метод формирования конечной цены
85+
calculateFinalPrice(initialPrice: number, userType: UserType, productTitle: ProductType): number {
86+
const discountAmount = (initialPrice / 100) * this.getCommonDiscount(userType, productTitle);
87+
return initialPrice - discountAmount;
88+
}
89+
}
90+
91+
export default AccountService;
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
export { default as AccountService } from './AccountService';
2+
export * from './interfaces';
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
export const enum UserType {
2+
Standard = 'Standard',
3+
Premium = 'Premium',
4+
Gold = 'Gold',
5+
Free = 'Free',
6+
}
7+
8+
export const enum ProductType {
9+
Car = 'Car',
10+
Toy = 'Toy',
11+
Food = 'Food',
12+
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import React from 'react';
2+
import { useTranslation } from 'react-i18next';
3+
import { Container } from '../../entities';
4+
import { AccountService, ProductType, UserType } from '../../features/AccountService';
5+
6+
export const AccountServicePage: React.FC = () => {
7+
// Пример использования класса AccountService
8+
const service = new AccountService();
9+
const userType = UserType.Premium;
10+
const initialPrice = 5000000;
11+
12+
const userDiscount = service.getDiscount(userType);
13+
const userProductDiscount = service.getUserProductDiscount(userType, ProductType.Car);
14+
const commonDiscount = service.getCommonDiscount(userType, ProductType.Car);
15+
const finalPrice = service.calculateFinalPrice(initialPrice, userType, ProductType.Car);
16+
17+
const discountListPromise = service.getUserProductsDiscountList();
18+
discountListPromise.then((result) => {
19+
console.log(result);
20+
});
21+
22+
const { t } = useTranslation();
23+
24+
return (
25+
<Container>
26+
<ul className="mb-4">
27+
<li>
28+
{t('accountServicePage.userDiscount')} {userDiscount * 100}%
29+
</li>
30+
<li>
31+
{t('accountServicePage.userProductDiscount')} {userProductDiscount * 100}%
32+
</li>
33+
</ul>
34+
<p className="mb-8">
35+
{t('accountServicePage.commonDiscount')} {commonDiscount}%
36+
</p>
37+
<p className="mb-4">
38+
{t('accountServicePage.initialPrice')} {initialPrice.toLocaleString()}&nbsp;₽
39+
</p>
40+
<p>
41+
{t('accountServicePage.finalPrice')} {finalPrice.toLocaleString()}&nbsp;₽
42+
</p>
43+
</Container>
44+
);
45+
};

src/pages/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
export { AccountServicePage } from './AccountServicePage/AccountServicePage';
12
export { Store } from './Store/Store';
23
export { StoreBasket } from './StoreBasket/StoreBasket';
34
export { StoreCard } from './StoreCard/StoreCard';

0 commit comments

Comments
 (0)