feat(t222): add freight ingestion admin flow
This commit is contained in:
@@ -922,6 +922,78 @@ func TestRendererUsesMissingKeyErrors(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestFreightPagesEscapeSourceDataAndCreateAsyncSync(t *testing.T) {
|
||||
now := time.Date(2026, 7, 28, 3, 4, 5, 0, time.UTC)
|
||||
service := &fakeFreightService{
|
||||
fakeService: &fakeService{},
|
||||
orders: []FreightOrder{{
|
||||
ID: testTaskID,
|
||||
ExternalStockID: "12",
|
||||
SourceCode: `<script>private</script>`,
|
||||
ShopName: "测试店铺",
|
||||
ItemCount: 2,
|
||||
Revision: 1,
|
||||
UpdatedAt: now,
|
||||
}},
|
||||
createResult: FreightSync{
|
||||
ID: testTaskID,
|
||||
Status: "PENDING",
|
||||
CreatedAt: now,
|
||||
},
|
||||
}
|
||||
router := newTestRouter(t, service)
|
||||
list := performRequest(t, router, http.MethodGet, "/freight", nil, "")
|
||||
if list.Code != http.StatusOK ||
|
||||
strings.Contains(list.Body.String(), `<script>private</script>`) ||
|
||||
!strings.Contains(list.Body.String(), "<script>private") ||
|
||||
!strings.Contains(list.Body.String(), "2 项") {
|
||||
t.Fatalf("freight list status/body = %d / %s", list.Code, list.Body)
|
||||
}
|
||||
assertSecurityHeaders(t, list)
|
||||
|
||||
form := performRequest(
|
||||
t,
|
||||
router,
|
||||
http.MethodGet,
|
||||
"/freight/import",
|
||||
nil,
|
||||
"",
|
||||
)
|
||||
cookie := csrfCookie(t, form)
|
||||
idempotencyKey := hiddenValue(
|
||||
t,
|
||||
form.Body.String(),
|
||||
"idempotency_key",
|
||||
)
|
||||
values := url.Values{
|
||||
"csrf_token": {cookie.Value},
|
||||
"idempotency_key": {idempotencyKey},
|
||||
"order_number": {"SOURCE-12"},
|
||||
}
|
||||
request := httptest.NewRequest(
|
||||
http.MethodPost,
|
||||
"/freight/import",
|
||||
strings.NewReader(values.Encode()),
|
||||
)
|
||||
request.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
||||
request.AddCookie(cookie)
|
||||
response := httptest.NewRecorder()
|
||||
router.ServeHTTP(response, request)
|
||||
if response.Code != http.StatusSeeOther ||
|
||||
response.Header().Get("Location") !=
|
||||
"/freight/import?sync="+testTaskID {
|
||||
t.Fatalf(
|
||||
"create sync status/location = %d / %q",
|
||||
response.Code,
|
||||
response.Header().Get("Location"),
|
||||
)
|
||||
}
|
||||
if service.createInput.OrderNumber != "SOURCE-12" ||
|
||||
service.createInput.IdempotencyKey != idempotencyKey {
|
||||
t.Fatalf("create input = %+v", service.createInput)
|
||||
}
|
||||
}
|
||||
|
||||
type fakeService struct {
|
||||
listInput ListTasksInput
|
||||
listResult TaskList
|
||||
@@ -945,6 +1017,45 @@ type fakeService struct {
|
||||
authorizeInput AuthorizeOrderInput
|
||||
}
|
||||
|
||||
type fakeFreightService struct {
|
||||
*fakeService
|
||||
orders []FreightOrder
|
||||
orderDetail FreightOrderDetail
|
||||
sync FreightSync
|
||||
createInput CreateFreightSyncInput
|
||||
createResult FreightSync
|
||||
err error
|
||||
}
|
||||
|
||||
func (service *fakeFreightService) ListFreightOrders(
|
||||
context.Context,
|
||||
int,
|
||||
) ([]FreightOrder, error) {
|
||||
return service.orders, service.err
|
||||
}
|
||||
|
||||
func (service *fakeFreightService) GetFreightOrder(
|
||||
context.Context,
|
||||
string,
|
||||
) (FreightOrderDetail, error) {
|
||||
return service.orderDetail, service.err
|
||||
}
|
||||
|
||||
func (service *fakeFreightService) GetFreightSync(
|
||||
context.Context,
|
||||
string,
|
||||
) (FreightSync, error) {
|
||||
return service.sync, service.err
|
||||
}
|
||||
|
||||
func (service *fakeFreightService) CreateFreightSync(
|
||||
_ context.Context,
|
||||
input CreateFreightSyncInput,
|
||||
) (FreightSync, error) {
|
||||
service.createInput = input
|
||||
return service.createResult, service.err
|
||||
}
|
||||
|
||||
func (service *fakeService) ListTasks(
|
||||
_ context.Context,
|
||||
input ListTasksInput,
|
||||
|
||||
Reference in New Issue
Block a user