You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

134 lines
4.0 KiB

import { describe, expect, it } from "vitest";
import {
buildPopiserverPriceQuoteRequest,
getQuotedPointAmount,
} from "@/utils/composerPricing";
import type { SelectedModel } from "@/types";
import type { GenerationNodeConfig } from "@/utils/generationConfig";
import type { ComposerPricingContext } from "@/utils/composerPricingContext";
function model(overrides: Partial<SelectedModel> = {}): SelectedModel {
return {
provider: "popiserver",
modelId: "popi-image",
displayName: "Popi Image",
capabilities: ["text-to-image"],
...overrides,
};
}
function draft(overrides: Partial<GenerationNodeConfig> = {}): GenerationNodeConfig {
return {
prompt: "prompt",
selectedModel: model(),
inputImages: [],
imageCount: 1,
referenceSubjectList: [],
parameters: {},
extraTaskParams: {},
...overrides,
};
}
function context(overrides: Partial<ComposerPricingContext> & { config?: GenerationNodeConfig } = {}): ComposerPricingContext {
return {
config: overrides.config ?? draft(),
capability: overrides.capability ?? "image",
media: overrides.media ?? {},
inputVideoDurationSeconds: overrides.inputVideoDurationSeconds ?? 0,
};
}
describe("composerPricing", () => {
it("builds PopiServer estimate payloads with provider model aliases", () => {
const request = buildPopiserverPriceQuoteRequest(context({
inputVideoDurationSeconds: 12,
config: draft({
selectedModel: model({
modelId: "123",
displayName: "Token billed video",
billingMethod: 2,
aiModelCode: "video-code",
aiModelCodeAlias: "video-alias",
}),
parameters: { duration: 8 },
}),
}));
expect(request).toEqual({
source: "estimate",
payload: {
model_name: "video-alias",
estimation_type: "auto",
parameters: {
duration: 8,
inputPrompt: "prompt",
input_video_duration_seconds: 12,
},
imageCount: 1,
input_video_duration_seconds: 12,
},
});
});
it("skips task price quote requests for llm and Seedance estimates", () => {
expect(buildPopiserverPriceQuoteRequest(context({
capability: "llm",
config: draft(),
}))).toBeNull();
expect(buildPopiserverPriceQuoteRequest(context({
capability: "video",
config: draft({
selectedModel: model({ displayName: "Seedance" }),
}),
}))).toMatchObject({ source: "estimate" });
});
it("uses PopiServer estimate only for billingMethod 2 or Seedance models", () => {
expect(buildPopiserverPriceQuoteRequest(context({ config: draft({
selectedModel: model({ billingMethod: 2 }),
}) }))).toMatchObject({ source: "estimate" });
expect(buildPopiserverPriceQuoteRequest(context({ config: draft({
selectedModel: model({
billingMethod: 1,
aiModelId: 32,
aiModelCode: "image-code",
type: 1,
subType: 101,
}),
}) }))).toMatchObject({ source: "task-price" });
expect(buildPopiserverPriceQuoteRequest(context({
capability: "video",
config: draft({
selectedModel: model({
displayName: "Seedance Pro",
billingMethod: 1,
}),
}),
}))).toMatchObject({ source: "estimate" });
});
it("builds unified PopiServer quote requests", () => {
const estimateContext = context({ config: draft({
selectedModel: model({ billingMethod: 2 }),
}) });
expect(buildPopiserverPriceQuoteRequest(estimateContext)).toMatchObject({
source: "estimate",
payload: {
estimation_type: "auto",
},
});
expect(buildPopiserverPriceQuoteRequest(context({ config: draft({
selectedModel: model({
billingMethod: 1,
aiModelId: 32,
}),
}) }))).toMatchObject({
source: "task-price",
});
expect(buildPopiserverPriceQuoteRequest(context())).toBeNull();
expect(getQuotedPointAmount({ data: { points: "36" } })).toBe(36);
expect(getQuotedPointAmount({ data: { points: "bad" } })).toBeNull();
});
});