Source code
Revision control
Copy as Markdown
Other Tools
Test Info: Warnings
- This test runs only with pattern: os != 'android'
- Manifest: browser/components/aiwindow/models/tests/xpcshell/xpcshell.toml
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
const { loadCallContext, loadPrompt, FEATURE_PURPOSES, DEFAULT_PURPOSE } =
ChromeUtils.importESModule(
"moz-src:///browser/components/aiwindow/models/PromptLoader.sys.mjs"
);
const { openAIEngine, MODEL_FEATURES } = ChromeUtils.importESModule(
"moz-src:///browser/components/aiwindow/models/Utils.sys.mjs"
);
const { sinon } = ChromeUtils.importESModule(
);
const PREF_MODEL = "browser.smartwindow.model";
const PREF_MODEL_CHOICE = "browser.smartwindow.firstrun.modelChoice";
const PREF_CUSTOM_PROMPTS = "browser.smartwindow.customPrompts";
registerCleanupFunction(() => {
for (const pref of [PREF_MODEL, PREF_MODEL_CHOICE, PREF_CUSTOM_PROMPTS]) {
if (Services.prefs.prefHasUserValue(pref)) {
Services.prefs.clearUserPref(pref);
}
}
});
add_task(async function test_loadCallContext_returns_expected_shape() {
Services.prefs.clearUserPref(PREF_MODEL);
Services.prefs.clearUserPref(PREF_MODEL_CHOICE);
const sb = sinon.createSandbox();
try {
const fakeRecords = [
{
feature: MODEL_FEATURES.CHAT,
version: "5.0",
model_choice_id: "",
model: "gpt-oss-120b",
is_default: true,
parameters: { temperature: 0.8 },
service_type: "ai",
purpose: "chat",
},
];
sb.stub(openAIEngine, "getRemoteClient").returns({
get: sb.stub().resolves(fakeRecords),
});
const ctx = await loadCallContext(MODEL_FEATURES.CHAT);
Assert.equal(ctx.model, "gpt-oss-120b", "model should be set from record");
Assert.deepEqual(
ctx.parameters,
{ temperature: 0.8 },
"parameters should be set from record"
);
Assert.equal(
ctx.serviceType,
"ai",
"serviceType should be set from record"
);
Assert.equal(ctx.purpose, "chat", "purpose should be set from record");
} finally {
sb.restore();
}
});
add_task(async function test_loadCallContext_falls_back_to_defaults() {
Services.prefs.clearUserPref(PREF_MODEL);
Services.prefs.clearUserPref(PREF_MODEL_CHOICE);
const sb = sinon.createSandbox();
try {
const fakeRecords = [
{
feature: MODEL_FEATURES.TITLE_GENERATION,
version: "1.0",
model: "some-model",
is_default: true,
},
];
sb.stub(openAIEngine, "getRemoteClient").returns({
get: sb.stub().resolves(fakeRecords),
});
const ctx = await loadCallContext(MODEL_FEATURES.TITLE_GENERATION);
Assert.deepEqual(
ctx.parameters,
{},
"parameters should default to empty object when absent"
);
Assert.equal(
ctx.serviceType,
"ai",
"serviceType should default to 'ai' for non-memories feature"
);
Assert.equal(
ctx.purpose,
FEATURE_PURPOSES[MODEL_FEATURES.TITLE_GENERATION] ??
FEATURE_PURPOSES[DEFAULT_PURPOSE],
"purpose should default to FEATURE_PURPOSES lookup"
);
} finally {
sb.restore();
}
});
add_task(async function test_loadCallContext_throws_on_missing_record() {
Services.prefs.clearUserPref(PREF_MODEL);
Services.prefs.clearUserPref(PREF_MODEL_CHOICE);
const sb = sinon.createSandbox();
try {
sb.stub(openAIEngine, "getRemoteClient").returns({
get: sb.stub().resolves([]),
});
await Assert.rejects(
loadCallContext(MODEL_FEATURES.CHAT),
/No Remote Settings records found for feature/,
"Should reject with a clear error when no records exist"
);
} finally {
sb.restore();
}
});
add_task(async function test_loadPrompt_returns_prompt_text() {
Services.prefs.clearUserPref(PREF_MODEL);
Services.prefs.clearUserPref(PREF_MODEL_CHOICE);
Services.prefs.clearUserPref(PREF_CUSTOM_PROMPTS);
const sb = sinon.createSandbox();
try {
const fakeRecords = [
{
feature: MODEL_FEATURES.CHAT,
version: "5.0",
model_choice_id: "",
model: "gpt-oss-120b",
is_default: true,
prompts: "You are a helpful assistant.",
},
];
sb.stub(openAIEngine, "getRemoteClient").returns({
get: sb.stub().resolves(fakeRecords),
});
const prompt = await loadPrompt(MODEL_FEATURES.CHAT);
Assert.equal(
prompt,
"You are a helpful assistant.",
"loadPrompt should return the prompts field from the record"
);
} finally {
sb.restore();
}
});
add_task(async function test_loadPrompt_throws_on_missing_record() {
Services.prefs.clearUserPref(PREF_MODEL);
Services.prefs.clearUserPref(PREF_MODEL_CHOICE);
Services.prefs.clearUserPref(PREF_CUSTOM_PROMPTS);
const sb = sinon.createSandbox();
try {
sb.stub(openAIEngine, "getRemoteClient").returns({
get: sb.stub().resolves([]),
});
await Assert.rejects(
loadPrompt(MODEL_FEATURES.CHAT),
/No Remote Settings records found for feature/,
"loadPrompt should reject when no records exist"
);
} finally {
sb.restore();
}
});
add_task(async function test_loadPrompt_honors_custom_prompt_pref() {
Services.prefs.clearUserPref(PREF_MODEL);
Services.prefs.clearUserPref(PREF_MODEL_CHOICE);
const sb = sinon.createSandbox();
try {
const fakeRecords = [
{
feature: MODEL_FEATURES.CHAT,
version: "5.0",
model_choice_id: "",
model: "gpt-oss-120b",
is_default: true,
prompts: "Original prompt.",
},
];
sb.stub(openAIEngine, "getRemoteClient").returns({
get: sb.stub().resolves(fakeRecords),
});
Services.prefs.setStringPref(
PREF_CUSTOM_PROMPTS,
JSON.stringify({ [MODEL_FEATURES.CHAT]: "OVERRIDE" })
);
const prompt = await loadPrompt(MODEL_FEATURES.CHAT);
Assert.equal(
prompt,
"OVERRIDE",
"loadPrompt should return the custom prompt pref override"
);
} finally {
Services.prefs.clearUserPref(PREF_CUSTOM_PROMPTS);
sb.restore();
}
});
add_task(
async function test_loadCallContext_remoteSettingsUnavailable_clientReason() {
const sb = sinon.createSandbox();
try {
sb.stub(openAIEngine, "getRemoteClient").returns({
get: sb.stub().resolves([]),
});
await Assert.rejects(
loadCallContext(MODEL_FEATURES.CHAT),
err => err.clientReason === "remoteSettingsUnavailable",
"loadCallContext should reject with clientReason remoteSettingsUnavailable"
);
} finally {
sb.restore();
}
}
);
add_task(
async function test_loadCallContext_modelConfigUnavailable_clientReason() {
const sb = sinon.createSandbox();
try {
// Records exist for the feature but not for the required major version,
// so selectMainConfig returns null and modelConfigUnavailable is reported.
const fakeRecords = [
{
feature: MODEL_FEATURES.CHAT,
version: "999.0",
model: "generic",
is_default: true,
},
];
sb.stub(openAIEngine, "getRemoteClient").returns({
get: sb.stub().resolves(fakeRecords),
});
await Assert.rejects(
loadCallContext(MODEL_FEATURES.CHAT),
err => err.clientReason === "modelConfigUnavailable",
"loadCallContext should reject with clientReason modelConfigUnavailable"
);
} finally {
sb.restore();
}
}
);
add_task(async function test_loadPrompt_promptLoadFailure_clientReason() {
const sb = sinon.createSandbox();
try {
// Record exists with a matching major version but no `prompts` field.
const fakeRecords = [
{
feature: MODEL_FEATURES.CHAT,
version: "5.0",
model: "generic",
is_default: true,
},
];
sb.stub(openAIEngine, "getRemoteClient").returns({
get: sb.stub().resolves(fakeRecords),
});
await Assert.rejects(
loadPrompt(MODEL_FEATURES.CHAT),
err => err.clientReason === "promptLoadFailure",
"loadPrompt should reject with clientReason promptLoadFailure"
);
} finally {
sb.restore();
}
});