Files
warp_engine/spec/services/publish_service_spec.rb
T
mr.zero 03a51a5b30 warp_engine 0.2.0: pluggable storage adapter and publish notifications
Two seams the hosts needed, both backward compatible.

Storage: artifacts are served through WarpEngine::Storage.adapter instead of
raw filesystem calls. The default :local adapter keeps the previous behaviour
byte for byte, including the path traversal guard. A host can now set
config.storage_adapter to any object answering file?/directory?/locate and
serve builds from an object store - FileService and /api/download both honour
a Location.redirect, so a signing adapter turns them into redirects.
DownloadService#create still returns an absolute path (nil when missing) for
existing callers; #locate is the new entry point that can also return a
redirect. Ingestion (upload, extraction, file manager) stays local for now.

Publish: PublishService emits ActiveSupport::Notifications
("warp_engine.publish") with platform/name/version/software/release, so hosts
can react to a new build without hanging callbacks on the models.
WarpEngine.instruments_publish? lets a host feature-detect and keep its
fallback for older engine versions.
2026-08-10 11:16:17 +02:00

93 lines
3.6 KiB
Ruby

require "rails_helper"
RSpec.describe WarpEngine::PublishService do
describe "#publish" do
it "raises ArgumentError for unsupported platform" do
input = WarpEngine::PublishInputDto.new(platform: "unknown", name: "game", version: "1.0")
expect { described_class.new.publish(input) }.to raise_error(ArgumentError, /Unsupported platform/)
end
it "routes to correct platform service" do
input = WarpEngine::PublishInputDto.new(platform: "tic80", name: "game", version: "1.0")
mock_service = instance_double(WarpEngine::Platforms::Tic80::Service)
allow(WarpEngine::Platforms::Tic80::Service).to receive(:new).and_return(mock_service)
allow(mock_service).to receive(:update)
described_class.new.publish(input)
expect(mock_service).to have_received(:update).with("game", "1.0")
end
it "routes godot platform to Godot::Service" do
input = WarpEngine::PublishInputDto.new(platform: "godot", name: "game", version: "1.0")
mock_service = instance_double(WarpEngine::Platforms::Godot::Service)
allow(WarpEngine::Platforms::Godot::Service).to receive(:new).and_return(mock_service)
allow(mock_service).to receive(:update)
described_class.new.publish(input)
expect(mock_service).to have_received(:update).with("game", "1.0")
end
it "routes bevy platform to Bevy::Service" do
input = WarpEngine::PublishInputDto.new(platform: "bevy", name: "game", version: "1.0")
mock_service = instance_double(WarpEngine::Platforms::Bevy::Service)
allow(WarpEngine::Platforms::Bevy::Service).to receive(:new).and_return(mock_service)
allow(mock_service).to receive(:update)
described_class.new.publish(input)
expect(mock_service).to have_received(:update).with("game", "1.0")
end
it "routes phaser platform to Phaser::Service" do
input = WarpEngine::PublishInputDto.new(platform: "phaser", name: "game", version: "1.0")
mock_service = instance_double(WarpEngine::Platforms::Phaser::Service)
allow(WarpEngine::Platforms::Phaser::Service).to receive(:new).and_return(mock_service)
allow(mock_service).to receive(:update)
described_class.new.publish(input)
expect(mock_service).to have_received(:update).with("game", "1.0")
end
describe "instrumentation" do
let(:input) { WarpEngine::PublishInputDto.new(platform: "tic80", name: "game", version: "1.0") }
let(:release) { WarpEngine::Release.new(version: "1.0") }
before do
mock_service = instance_double(WarpEngine::Platforms::Tic80::Service, update: release)
allow(WarpEngine::Platforms::Tic80::Service).to receive(:new).and_return(mock_service)
end
# The host reacts to a new build through this event instead of hanging a
# callback on the Release model.
it "emits warp_engine.publish with the release in the payload" do
payloads = []
ActiveSupport::Notifications.subscribe(described_class::NOTIFICATION) do |*, payload|
payloads << payload
end
described_class.new.publish(input)
expect(payloads.size).to eq(1)
expect(payloads.first).to include(platform: "tic80", name: "game", version: "1.0", release: release)
ensure
ActiveSupport::Notifications.unsubscribe(described_class::NOTIFICATION)
end
it "returns the release" do
expect(described_class.new.publish(input)).to eq(release)
end
it "advertises the feature so older hosts can feature-detect" do
expect(WarpEngine.instruments_publish?).to be(true)
end
end
end
end