Comments (9)
VSCode 忽略搜索哪些文件夹
"search.exclude": {
"**/.git": true,
"**/build": true,
"**/node_molecules": true,
"**/bower_components": true,
"**/tmp": true
}
from annewanghy.github.io.
use Hugo to make a blog
based on go
quicker than Hexo
from annewanghy.github.io.
frontend/containers/product/index.tsx
Product.getInitialProps = ({
query,
context
}: InitialProps): Promise<ProductProps> => {
const productCode: api.IProductCode = { code: (query && query.code) || "" };
if (!productCode.code) {
throw errNotFound;
}
const service = makeService(api.ProductService, context);
return service.getProduct(productCode).then(productResponse => {
if (!productResponse.product) {
throw errNotFound;
}
const properties: base.IProperty[] =
(productResponse.product && productResponse.product.filterProperties) ||
[];
const topLevelCategory: base.IProperty = properties.find(
({ field }) => field === "TopLevelCategory"
) || { values: [] };
const filterProperties: products.IFilterProperty[] = [
{
field: "TopLevelCategory",
groupType: products.FilterGroupType.PRODUCT,
inValues: topLevelCategory.values
}
];
return service
.filterProducts({ filterProperties, page: 1, perPage: 5 })
.then(({ result, rdGroups }) => {
const products = ((result && result.products) || [])
.filter(({ code }) => code !== productCode.code)
.slice(0, 4);
const productsResponse: api.IProductsResponse = {
products,
rdGroups
};
return {
productResponse,
productsResponse
} as ProductProps;
});
});
};
api/products.proto
api.ProductService
上面用到了GetProduct (ProductCode) returns (ProductResponse)
这个方法
service ProductService {
rpc GetProduct (ProductCode) returns (ProductResponse);
rpc GetProducts (ProductCodes) returns (ProductsResponse);
rpc GetFilterGroups (products.SearchOptions) returns (FilterProductsResponse);
rpc FilterProducts (products.SearchOptions) returns (FilterProductsResponse);
}
没有找到,就throw一个errorNotFound的错误, 输出错误信息product not found
const errNotFound = new ProductNotFound(404);
class ProductNotFound extends Error {
constructor(public statusCode: number) {
super("product not found");
}
}
frontend/proto.d.ts文件里面可以找到base.IProperty
export namespace base {
/** Properties of a Property. */
interface IProperty {
/** Property field */
field?: string;
/** Property values */
values?: string[];
}
...
}
/** for filter products */
namespace products下的interface IProduct有这个过滤属性,类型就是base.IProperty
filterProperties?: base.IProperty[];
const properties: base.IProperty[] =
(productResponse.product && productResponse.product.filterProperties) ||
[];
而base.IProperty是namespace base下的interface IProperty,这个接口需要两个可选参数filed,和values
const topLevelCategory: base.IProperty = properties.find(
({ field }) => field === "TopLevelCategory") || { values: [] };
设置过滤条件为*TopLevelCategory*, 需要修改为*TopLevelCollection*
const filterProperties: products.IFilterProperty[] = [
{
field: "TopLevelCategory",
groupType: products.FilterGroupType.PRODUCT,
inValues: topLevelCategory.values
}
];
class SearchOptions { //选择条件
class AggregateCondition {//合计条件
interface IFilterProperty { // 过滤属性
/** FilterProperty field */
field?: string;
/** FilterProperty groupType */
groupType?: products.FilterGroupType;
/** FilterProperty inValues */
inValues?: string[];
/** FilterProperty isNegative */
isNegative?: boolean;
}
}
}
return service
.filterProducts({ filterProperties, page: 1, perPage: 5 }) // 用到了page, perPage和filterProperties三个可选参数
.then(({ result, rdGroups }) => {// 用到了返回函数的result和rdGroups两个参数
const products = ((result && result.products) || []) // 得到返回的结果是result.products
.filter(({ code }) => code !== productCode.code)
.slice(0, 4);
const productsResponse: api.IProductsResponse = {
products,
rdGroups
};
return {
productResponse,
productsResponse
} as ProductProps;
});
ProductService{
//返回一个Promise对象
public filterProducts(request: products.ISearchOptions): Promise<api.FilterProductsResponse>;
}
输入参数
products.ISearchOptions
/** Properties of a SearchOptions. */
interface ISearchOptions {
/** SearchOptions keyword */
keyword?: string;
/** SearchOptions page */
page?: (number|Long);
/** SearchOptions perPage */
perPage?: (number|Long);
/** SearchOptions filterProperties */
filterProperties?: products.IFilterProperty[];
/** SearchOptions sorters */
sorters?: products.ISorter[];
/** SearchOptions conditions */
conditions?: products.FilterCondition[];
/** SearchOptions filterGroups */
filterGroups?: products.ISearchFilterGroup[];
/** SearchOptions filterGroupMode */
filterGroupMode?: products.SearchFilterGroupMode;
/** SearchOptions path */
path?: string;
/** SearchOptions publishReady */
publishReady?: (number|Long);
/** SearchOptions scheduledAt */
scheduledAt?: string;
}
返回参数
class FilterProductsResponse {
/**
* Constructs a new FilterProductsResponse.
* @param [properties] Properties to set
*/
constructor(properties?: api.IFilterProductsResponse);
/** FilterProductsResponse result. */
public result?: (products.IFilterProductsResult|null);
/** FilterProductsResponse rdGroups. */
public rdGroups: referencedata.IRDGroup[];
...
}
/** Properties of a FilterProductsResult. */
interface IFilterProductsResult {
/** FilterProductsResult products */
products?: products.IProduct[];
/** FilterProductsResult filterGroups */
filterGroups?: products.IFilterGroup[];
/** FilterProductsResult total */
total?: (number|Long);
}
from annewanghy.github.io.
主要是解决将topLevelCategory换成topLevelCollection的问题
frontend/product/productField.ts
enum ProductField {
TopLevelCategory = "TopLevelCategory",
SubCategory = "SubCategory",
Collection = "Collection",
Material = "Material",
ColorDescription = "ColorDescription",
Size = "Size",
TotalLength = "TotalLength",
MaximumWidth = "MaximumWidth"
}
TopLevelCategory
{"categories":{"items":[{"itemType":"TopLevelCategory","code":"TC1","slug":"earrings","name":"ピアス(イヤリング)","description":"多くの文化で身分や美しさの象徴として用いられている。かつては、奴隷身分を示すため、耳から外すことのできないタイプのものが用いられていたところもある。","images":[{"device":"MOBILE","url":"//mastani-dev.s3-ap-southeast-1.amazonaws.com/reference_data_item_images/6/image/key-visual-1.20171109052617018896809.png"},{"device":"LAPTOP","url":"//mastani-dev.s3-ap-southeast-1.amazonaws.com/reference_data_item_images/5/image/key-visual.20171109054317787731532.png","purpose":"earrings category"}]},{"itemType":"TopLevelCategory","code":"TC2","slug":"rings","name":"リング"},{"itemType":"TopLevelCategory","code":"TC3","slug":"necklace","name":"ネックレス"},{"itemType":"TopLevelCategory","code":"TC4","slug":"bracelet","name":"ブレスレット"},{"itemType":"TopLevelCategory","code":"TC5","slug":"brooch","name":"ブローチ"},{"itemType":"TopLevelCategory","code":"TC6","slug":"pendant","name":"ペンダント"},{"itemType":"TopLevelCategory","code":"TC7","slug":"brooch","name":"ブローチ"},{"itemType":"TopLevelCategory","code":"TC8","slug":"accessories","name":"アクセサリー","images":[{"device":"MOBILE","url":"//mastani-dev.s3.ap-southeast-1.amazonaws.com/reference_data_item_images/1/image/anime-like-fate-stay-night.20171102081417498370912.jpg","purpose":"collection page"}]}]},"isOnCartPage":false}
frontend/index.ts
const CollectionList = (limit?: number) => {
const List = ((props: Props) => (
<Responsive>
{(desktop: boolean) =>
desktop ? <DesktopList {...props} /> : <MobileList {...props} />}
</Responsive>
)) as Container<Props>;
List.getInitialProps = ({ context }: InitialProps): Promise<Props> =>
makeService(api.ReferenceDataService, context)
.getItems({ fetchAll: true, itemType: "Collection" })
.then(({ items }) => {
items = items.filter(
({ images }) => images != null && images.length > 0
);
if (limit != null) {
items = items.slice(0, limit);
}
return { items };
});
return List;
};
TopLevelCategory
{filterProperties: Array(1), page: 1, perPage: 5}
filterProperties:Array(1)
field:"TopLevelCategory"
groupType:0
inValues:"TC1"
Collection
{filterProperties: Array(1), page: 1, perPage: 5}
filterProperties:Array(1)
field:"Collection"
groupType:0
inValues:["CL4"]
但是最后和Jaden讨论之后,明白产品没有collection这个属性,而是用TopLevelCategory.
那就是不需要修改原来junhui写的内容
from annewanghy.github.io.
学习怎么使用postman调用后台数据
导入团队开发的.json文件,然后换到collection的tab页面,发送send请求就可以获取API的数据
本地的API数据 http://localhost:9800/api/ja/api.ProductService/FilterProducts
更换为远程的API数据 https://mastani-api.dt.theplant-dev.com/api/ja/api.ProductService/FilterProducts
from annewanghy.github.io.
Promise没有完成
product/index.test.tsx
现在的写法用then来调用filter是错误的,因此还需要修改
半成品
import Product from ".";
import { ProductProps } from "./mobile";
import { api, products, base } from "../../proto";
import { productResponse, productsResponse } from "./fakeData";
import { testContext } from "../../testHelper";
const properties: base.IProperty[] =
(productResponse.product && productResponse.product.filterProperties) ||
[];
const topLevelCategory: base.IProperty = properties.find(
({ field }) => field === "TopLevelCategory"
) || { values: [] };
const filterProperties: products.IFilterProperty[] = [
{
field: "TopLevelCategory",
groupType: products.FilterGroupType.PRODUCT,
inValues: topLevelCategory.values
}
];
describe("Product.getInitialProps", () => {
test("happy filter path", async () => {
const response: typeof api.ProductService.prototype.getProduct(productResponse.product.code) = () =>
Promise
.resolve(new api.ProductResponse(productResponse))
.then(() => {
const filterResponse: typeof api.ProductService.prototype.filterProducts({ filterProperties, page: 1, perPage: 5 })= () =>
Promise.resolve(new api.FilterProductsResponse(productsResponse))
})
api.ProductService.prototype.getProduct = jest.fn(response);
const props = await Product.getInitialProps(testContext());
const expected: ProductProps = { productResponse: productResponse, productsResponse: productsResponse};
expect(props).toMatchObject(expected);
});
test("failing filter API call", () => {
const error = new Error("test error");
api.ProductService.prototype.filterProducts = jest.fn(() =>
Promise.reject(error)
);
expect.hasAssertions();
return expect(Product.getInitialProps(testContext())).rejects.toBe(error);
});
test("failing API call", () => {
const error = new Error("test error");
api.ProductService.prototype.getProduct = jest.fn(() =>
Promise.reject(error)
);
expect.hasAssertions();
return expect(Product.getInitialProps(testContext())).rejects.toBe(error);
});
});
from annewanghy.github.io.
import Product from ".";
import { ProductProps } from "./mobile";
import { api } from "../../proto";
import { productResponse, productsResponse } from "./fakeData";
import { testContext } from "../../testHelper";
describe("Product.getInitialProps", () => {
test("happy path", async () => {
const getProductResponse: typeof api.ProductService.prototype.getProduct = () =>
Promise.resolve(new api.ProductResponse(productResponse));
const getProductsResponse: typeof api.ProductService.prototype.getFilterGroups = () =>
Promise.resolve(new api.FilterProductsResponse(productsResponse));
api.ProductService.prototype.getProduct = jest.fn(getProductResponse);
api.ProductService.prototype.getFilterGroups = jest.fn(getProductsResponse);
const props = await Product.getInitialProps({
...testContext(),
query: { code: "xxx" }
});
const expected: ProductProps = {
productResponse: productResponse,
productsResponse: productsResponse
};
expect(props).toMatchObject(expected);
});
test("failing API call", () => {
const error = new Error("test error");
api.ProductService.prototype.getProduct = jest.fn(() =>
Promise.reject(error)
);
api.ProductService.prototype.getFilterGroups = jest.fn(() =>
Promise.reject(error)
);
expect.hasAssertions();
return expect(
Product.getInitialProps({ ...testContext(), query: { code: "xxx" } })
).rejects.toBe(error);
});
});
from annewanghy.github.io.
总共12个case
- error
- without code - > throw errorNotFound
- make service error
- service.getProduct error
- service.filterProducts error
- no error
- filterProperties[0].inValues
- dosen't has topLevelCategory.values
- has topLevelCategory.values
- filterProducts
- filterProducts dosen't contain product
- filterProducts contain product
- filterProducts === null, productsResponse = null
- filterProducts.length in (1,4) , productsResponse = filterProducts.length
- filterProducts.length >4 , productsResponse = 4
- filterProperties[0].inValues
from annewanghy.github.io.
first try
import Product from ".";
import { ProductProps } from "./mobile";
import { api } from "../../proto";
import {
productResponse,
filterProductsResponse,
filteredProductsResponse
} from "./fakeData";
import { testContext } from "../../testHelper";
describe("throw error", () => {
test("fail to get product code", () => {
const error = new Error("fail to get product code");
expect.hasAssertions();
return expect(
Product.getInitialProps({
...testContext()
})
).rejects.toEqual(error);
});
test("fail to make service", () => {
const error = new RangeError("index out of range: 5 + 4 > 7");
expect.hasAssertions();
return expect(
Product.getInitialProps({
...testContext(),
query: {
code: "ES-43"
}
})
).rejects.toEqual(error);
});
test("fail to call api getProduct", () => {
const error = new Error("getProduct error");
api.ProductService.prototype.getProduct = jest.fn(() =>
Promise.reject(error)
);
expect.hasAssertions();
return expect(
Product.getInitialProps({
...testContext(),
query: {
code: "ES-43"
}
})
).rejects.toEqual(error);
});
test("fail to call api getFilterGroups", () => {
const error = new Error("getProduct error");
api.ProductService.prototype.getFilterGroups = jest.fn(() =>
Promise.reject(error)
);
expect.hasAssertions();
return expect(
Product.getInitialProps({
...testContext(),
query: {
code: "ES-43"
}
})
).rejects.toEqual(error);
});
test("failing API call", () => {
const error = new Error("test error");
api.ProductService.prototype.getProduct = jest.fn(() =>
Promise.reject(error)
);
api.ProductService.prototype.getFilterGroups = jest.fn(() =>
Promise.reject(error)
);
expect.hasAssertions();
return expect(
Product.getInitialProps({
...testContext(),
query: {
code: "ES-43"
}
})
).rejects.toEqual(error);
});
});
describe("Product.getInitialProps", () => {
test("happy path", async () => {
const getProductResponse: typeof api.ProductService.prototype.getProduct = () =>
Promise.resolve(new api.ProductResponse(productResponse));
const getFilterProductsResponse: typeof api.ProductService.prototype.filterProducts = () =>
Promise.resolve(new api.FilterProductsResponse(filterProductsResponse));
api.ProductService.prototype.getProduct = jest.fn(getProductResponse);
api.ProductService.prototype.filterProducts = jest.fn(
getFilterProductsResponse
);
const props = await Product.getInitialProps({
...testContext(),
query: {
code: "ES-43"
}
});
const expected: ProductProps = {
productResponse: productResponse,
productsResponse: filteredProductsResponse
};
expect(props).toMatchObject(expected);
});
});
describe("test filter data", () => {
const cases: Array<
[string, string | null, Array<String> | null, {} | any]
> = [
[
"filtered products don't contain the product",
"ES-00",
["ES-01", "ES-02", "ES-03"],
["ES-01", "ES-02", "ES-03"]
],
[
"filtered products contain the product",
"ES-00",
["ES-00", "ES-01", "ES-02"],
["ES-01", "ES-02"]
],
["filtered products = null", null, null, null],
[
"filtered products's length <= 4 and doesn't contain product",
"ES-00",
["ES-01"],
["ES-01"]
],
[
"filtered products'length>4 and doesn't contain the product",
"ES-00",
["ES-01", "ES-02", "ES-03", "ES-04", "ES-05"],
["ES-01", "ES-02", "ES-03", "ES-04"]
]
];
cases.forEach(([desc, productCode, filterProduct, filteredProduct]) => {
test(`${desc}`, () => {
var filterProductResult: Array<String> | null = new Array();
if (filterProduct && filterProduct.length <= 4) {
filterProductResult = ((filterProduct && filterProduct) || []).filter(
product => product !== productCode
);
} else {
filterProductResult = ((filterProduct && filterProduct) || [])
.filter(product => product !== productCode)
.slice(0, 4);
}
expect(filterProductResult).toMatchObject(filteredProduct);
});
});
});
两个错误“Expected at least one assertion to be called but received none.”
一个不匹配
from annewanghy.github.io.
Related Issues (20)
- 前端面试题-回答 HOT 1
- 学计算机单词 HOT 12
- 日记
- React&Redux-TodoList HOT 1
- 发现了一个超级棒的GitHub开源项目-快速搭建一个静态的react网站
- 网页版在线工具
- 2017-10
- Mac使用积累 HOT 3
- use next.js HOT 2
- 想法 HOT 3
- Todo HOT 39
- 2017-12-4 HOT 2
- 2017-12-5 HOT 1
- Css积累
- vim学习之路 HOT 3
- Little tips HOT 2
- Create a code Snipper by VSCode
- Darams
- Learn and Use React-Native
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from annewanghy.github.io.