141 lines
3.8 KiB
Ruby
141 lines
3.8 KiB
Ruby
|
# frozen_string_literal: true
|
||
|
|
||
|
require "rails_helper"
|
||
|
|
||
|
RSpec.describe DiscourseAi::Admin::AiUsageController do
|
||
|
fab!(:admin)
|
||
|
fab!(:user)
|
||
|
let(:usage_path) { "/admin/plugins/discourse-ai/ai-usage.json" }
|
||
|
|
||
|
before { SiteSetting.discourse_ai_enabled = true }
|
||
|
|
||
|
context "when logged in as admin" do
|
||
|
before { sign_in(admin) }
|
||
|
|
||
|
describe "#show" do
|
||
|
fab!(:log1) do
|
||
|
AiApiAuditLog.create!(
|
||
|
provider_id: 1,
|
||
|
feature_name: "summarize",
|
||
|
language_model: "gpt-4",
|
||
|
request_tokens: 100,
|
||
|
response_tokens: 50,
|
||
|
created_at: 1.day.ago,
|
||
|
)
|
||
|
end
|
||
|
|
||
|
fab!(:log2) do
|
||
|
AiApiAuditLog.create!(
|
||
|
provider_id: 1,
|
||
|
feature_name: "translate",
|
||
|
language_model: "gpt-3.5",
|
||
|
request_tokens: 200,
|
||
|
response_tokens: 100,
|
||
|
created_at: 2.days.ago,
|
||
|
)
|
||
|
end
|
||
|
|
||
|
it "returns correct data structure" do
|
||
|
get usage_path
|
||
|
|
||
|
expect(response.status).to eq(200)
|
||
|
|
||
|
json = response.parsed_body
|
||
|
expect(json).to have_key("data")
|
||
|
expect(json).to have_key("features")
|
||
|
expect(json).to have_key("models")
|
||
|
expect(json).to have_key("summary")
|
||
|
end
|
||
|
|
||
|
it "respects date filters" do
|
||
|
get usage_path, params: { start_date: 3.days.ago.to_date, end_date: 1.day.ago.to_date }
|
||
|
|
||
|
json = response.parsed_body
|
||
|
expect(json["summary"]["total_tokens"]).to eq(450) # sum of all tokens
|
||
|
end
|
||
|
|
||
|
it "filters by feature" do
|
||
|
get usage_path, params: { feature: "summarize" }
|
||
|
|
||
|
json = response.parsed_body
|
||
|
|
||
|
features = json["features"]
|
||
|
expect(features.length).to eq(1)
|
||
|
expect(features.first["feature_name"]).to eq("summarize")
|
||
|
expect(features.first["total_tokens"]).to eq(150)
|
||
|
end
|
||
|
|
||
|
it "filters by model" do
|
||
|
get usage_path, params: { model: "gpt-3.5" }
|
||
|
|
||
|
json = response.parsed_body
|
||
|
models = json["models"]
|
||
|
expect(models.length).to eq(1)
|
||
|
expect(models.first["llm"]).to eq("gpt-3.5")
|
||
|
expect(models.first["total_tokens"]).to eq(300)
|
||
|
end
|
||
|
|
||
|
it "handles different period groupings" do
|
||
|
get usage_path, params: { period: "hour" }
|
||
|
expect(response.status).to eq(200)
|
||
|
|
||
|
get usage_path, params: { period: "month" }
|
||
|
expect(response.status).to eq(200)
|
||
|
end
|
||
|
end
|
||
|
|
||
|
# spec/requests/admin/ai_usage_controller_spec.rb
|
||
|
context "with hourly data" do
|
||
|
before do
|
||
|
freeze_time Time.parse("2021-02-01 00:00:00")
|
||
|
# Create data points across different hours
|
||
|
[23.hours.ago, 22.hours.ago, 21.hours.ago, 20.hours.ago].each do |time|
|
||
|
AiApiAuditLog.create!(
|
||
|
provider_id: 1,
|
||
|
feature_name: "summarize",
|
||
|
language_model: "gpt-4",
|
||
|
request_tokens: 100,
|
||
|
response_tokens: 50,
|
||
|
created_at: time,
|
||
|
)
|
||
|
end
|
||
|
end
|
||
|
|
||
|
it "returns hourly data when period is day" do
|
||
|
get usage_path, params: { start_date: 1.day.ago.to_date, end_date: Time.current.to_date }
|
||
|
|
||
|
expect(response.status).to eq(200)
|
||
|
json = response.parsed_body
|
||
|
|
||
|
expect(json["data"].length).to eq(4)
|
||
|
|
||
|
data_by_hour = json["data"].index_by { |d| Time.parse(d["period"]).hour }
|
||
|
|
||
|
expect(data_by_hour.keys.length).to eq(4)
|
||
|
expect(data_by_hour.first[1]["total_tokens"]).to eq(150)
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
context "when not admin" do
|
||
|
before { sign_in(user) }
|
||
|
|
||
|
it "blocks access" do
|
||
|
get usage_path
|
||
|
expect(response.status).to eq(404)
|
||
|
end
|
||
|
end
|
||
|
|
||
|
context "when plugin disabled" do
|
||
|
before do
|
||
|
SiteSetting.discourse_ai_enabled = false
|
||
|
sign_in(admin)
|
||
|
end
|
||
|
|
||
|
it "returns error" do
|
||
|
get usage_path
|
||
|
expect(response.status).to eq(404)
|
||
|
end
|
||
|
end
|
||
|
end
|