diff --git a/codegen/projections/white_label/lib/white_label/stubs.rb b/codegen/projections/white_label/lib/white_label/stubs.rb index 8594d6067..0a3cfaddf 100644 --- a/codegen/projections/white_label/lib/white_label/stubs.rb +++ b/codegen/projections/white_label/lib/white_label/stubs.rb @@ -819,6 +819,16 @@ def self.stub(http_resp, stub:) http_resp.body = message http_resp.status = 200 end + + def self.default_event(visited = []) + return nil if visited.include?('Events') + visited = visited + ['Events'] + Params::SimpleEvent.build( + SimpleEvent.default(visited), + context: 'default_event' + ) + end + def self.validate_event!(event, context:) case event when Types::Events::SimpleEvent @@ -1080,9 +1090,6 @@ def self.stub(stub) message end end - - class StartEventStreamInitialResponse - end end end end diff --git a/codegen/projections/white_label/spec/event_stream_stubs_spec.rb b/codegen/projections/white_label/spec/event_stream_stubs_spec.rb index 4555c45a3..2f72fa124 100644 --- a/codegen/projections/white_label/spec/event_stream_stubs_spec.rb +++ b/codegen/projections/white_label/spec/event_stream_stubs_spec.rb @@ -220,21 +220,27 @@ end end - context 'API error response' do - it 'signals the error' do - subject.stub_responses(:start_event_stream, - WhiteLabel::Errors::ClientError.new( - http_resp: Hearth::HTTP2::Response.new, - error_code: 'ClientError' - )) + context 'default stubs' do + let(:default_message) { 'message' } + it 'stubs a default initial response and event' do - event_handler.on_error(&handler) + event_handler.on_initial_response(&handler) + event_handler.on_simple_event(&handler) - expect(handler).to receive(:call) do |error| - expect(error).to be_a(WhiteLabel::Errors::ClientError) + expect(handler).to receive(:call) do |event| + expect(event).to be_a(WhiteLabel::Types::StartEventStreamOutput) + expect(event.initial_structure.message).to eq(default_message) + end + + + expect(handler).to receive(:call) do |event| + expect(event) + .to be_a(WhiteLabel::Types::Events::SimpleEvent) + expect(event.message).to eq(default_message) end subject.start_event_stream({}, event_stream_handler: event_handler) end end + end diff --git a/codegen/projections/white_label/spec/middleware_spec.rb b/codegen/projections/white_label/spec/middleware_spec.rb index 34a1c9d61..fd8c29f53 100644 --- a/codegen/projections/white_label/spec/middleware_spec.rb +++ b/codegen/projections/white_label/spec/middleware_spec.rb @@ -75,7 +75,8 @@ module WhiteLabel client: client.config.http_client, stub_error_classes: anything, stub_data_class: anything, - stub_message_encoder: anything) + stub_message_encoder: anything, + response_events: anything) .and_call_original client.kitchen_sink diff --git a/codegen/smithy-ruby-codegen-test/integration-specs/event_stream_stubs_spec.rb b/codegen/smithy-ruby-codegen-test/integration-specs/event_stream_stubs_spec.rb index 4555c45a3..560eac8f5 100644 --- a/codegen/smithy-ruby-codegen-test/integration-specs/event_stream_stubs_spec.rb +++ b/codegen/smithy-ruby-codegen-test/integration-specs/event_stream_stubs_spec.rb @@ -237,4 +237,25 @@ subject.start_event_stream({}, event_stream_handler: event_handler) end end + + context 'default stubs' do + let(:default_message) { 'message' } + it 'stubs a default initial response and event' do + event_handler.on_initial_response(&handler) + event_handler.on_simple_event(&handler) + + expect(handler).to receive(:call) do |event| + expect(event).to be_a(WhiteLabel::Types::StartEventStreamOutput) + expect(event.initial_structure.message).to eq(default_message) + end + + expect(handler).to receive(:call) do |event| + expect(event) + .to be_a(WhiteLabel::Types::Events::SimpleEvent) + expect(event.message).to eq(default_message) + end + + subject.start_event_stream({}, event_stream_handler: event_handler) + end + end end diff --git a/codegen/smithy-ruby-codegen-test/integration-specs/middleware_spec.rb b/codegen/smithy-ruby-codegen-test/integration-specs/middleware_spec.rb index 34a1c9d61..fd8c29f53 100644 --- a/codegen/smithy-ruby-codegen-test/integration-specs/middleware_spec.rb +++ b/codegen/smithy-ruby-codegen-test/integration-specs/middleware_spec.rb @@ -75,7 +75,8 @@ module WhiteLabel client: client.config.http_client, stub_error_classes: anything, stub_data_class: anything, - stub_message_encoder: anything) + stub_message_encoder: anything, + response_events: anything) .and_call_original client.kitchen_sink diff --git a/codegen/smithy-ruby-codegen/src/main/java/software/amazon/smithy/ruby/codegen/generators/StubsGeneratorBase.java b/codegen/smithy-ruby-codegen/src/main/java/software/amazon/smithy/ruby/codegen/generators/StubsGeneratorBase.java index b42db2e3c..038c94c26 100644 --- a/codegen/smithy-ruby-codegen/src/main/java/software/amazon/smithy/ruby/codegen/generators/StubsGeneratorBase.java +++ b/codegen/smithy-ruby-codegen/src/main/java/software/amazon/smithy/ruby/codegen/generators/StubsGeneratorBase.java @@ -308,7 +308,6 @@ private void renderStubs() { } if (Streaming.isEventStreaming(model, outputShape)) { - eventStreamEventsToRender.add(o); // to handle initial-response events for (MemberShape memberShape : outputShape.members()) { if (StreamingTrait.isEventStream(model, memberShape)) { UnionShape eventStreamUnion = model.expectShape( @@ -343,27 +342,12 @@ private void renderStubs() { // Render all shapes in alphabetical ordering eventStreamEventsToRender .forEach(shape -> { - if (shape.isOperationShape()) { - // initial-response - writer - .write("") - .openBlock("class $LInitialResponse", - symbolProvider.toSymbol(shape).getName()) - .call(() -> renderInitialResponseEventStubMethod( - model.expectShape( - shape.asOperationShape().get().getOutputShape(), - StructureShape.class) - ) - ) - .closeBlock("end"); - } else { - // Event stream event members MUST target only StructureShapes - writer - .write("") - .openBlock("class $L", symbolProvider.toSymbol(shape).getName()) - .call(() -> renderEventStubMethod(shape.asStructureShape().get())) - .closeBlock("end"); - } + // Event stream event members MUST target only StructureShapes + writer + .write("") + .openBlock("class $L", symbolProvider.toSymbol(shape).getName()) + .call(() -> renderEventStubMethod(shape.asStructureShape().get())) + .closeBlock("end"); }); }) .closeBlock("end"); @@ -436,6 +420,8 @@ private void renderStubsForOperation(OperationShape operation, Shape outputShape UnionShape eventStreamUnion = model.expectShape( Streaming.getEventStreamMember(model, outputShape).get().getTarget(), UnionShape.class); + renderDefaultEventMethod(eventStreamUnion); + writer.write(""); renderValidateEventMethod(eventStreamUnion); writer.write(""); renderStubEventMethod(eventStreamUnion); @@ -463,6 +449,26 @@ private void renderStubEventMethod(UnionShape eventStreamUnion) { .closeBlock("end"); } + private void renderDefaultEventMethod(UnionShape eventStreamUnion) { + String name = symbolProvider.toSymbol(eventStreamUnion).getName(); + writer + .write("") + .openBlock("def self.default_event(visited = [])") + .write("return nil if visited.include?('$L')", name) + .write("visited = visited + ['$L']", name) + .call(() -> { + MemberShape defaultMember = eventStreamUnion.members().iterator().next(); + Shape target = model.expectShape(defaultMember.getTarget()); + String className = symbolProvider.toSymbol(target).getName(); + writer.openBlock("Params::$L.build(", className); + String symbolName = RubyFormatter.toSnakeCase(symbolProvider.toMemberName(defaultMember)); + target.accept(new MemberDefaults("", ",", symbolName)); + writer.write("context: 'default_event'"); + writer.closeBlock(")"); + }) + .closeBlock("end"); + } + private void renderValidateEventMethod(UnionShape eventStreamUnion) { writer .openBlock("def self.validate_event!(event, context:)") diff --git a/hearth/lib/hearth/middleware/send.rb b/hearth/lib/hearth/middleware/send.rb index 120facde4..5ed3d3919 100755 --- a/hearth/lib/hearth/middleware/send.rb +++ b/hearth/lib/hearth/middleware/send.rb @@ -276,13 +276,15 @@ def apply_initial_response(response, context) end def apply_stub_nil_event(context) - # TODO - # output = @stub_data_class.build( - # @stub_data_class.default, - # context: 'stub' - # ) - # @stub_data_class.validate!(output, context: 'stub') - # @stub_data_class.stub(context.response, stub: output) + apply_initial_response_stub( + @stub_data_class.default, + context + ) + + apply_stub_event_structure( + @stub_data_class.default_event, + context + ) end def apply_stub_event_api_error(api_error, context)