@Test
  public void shouldSendEventWhenChannelWasUpdated() {
    Channel channel = new Channel("displayName", BUNDLE_SYMBOLIC_NAME, VERSION);

    EventParameter eventParameter = new EventParameter("displayName", "eventKey");
    TriggerEvent triggerEvent =
        new TriggerEvent("displayName", "subject", null, Arrays.asList(eventParameter), "");

    channel.getTriggerTaskEvents().add(triggerEvent);

    when(channelsDataService.findByModuleName(channel.getModuleName())).thenReturn(channel);

    when(bundleContext.getBundles()).thenReturn(new Bundle[] {bundle});
    when(bundle.getSymbolicName()).thenReturn(BUNDLE_SYMBOLIC_NAME);

    ArgumentCaptor<MotechEvent> captor = ArgumentCaptor.forClass(MotechEvent.class);
    Channel updatedChannel = new Channel("displayName2", BUNDLE_SYMBOLIC_NAME, VERSION);
    updatedChannel.getTriggerTaskEvents().add(triggerEvent);
    channelService.addOrUpdate(updatedChannel);

    ArgumentCaptor<TransactionCallback> transactionCaptor =
        ArgumentCaptor.forClass(TransactionCallback.class);
    verify(channelsDataService).doInTransaction(transactionCaptor.capture());
    transactionCaptor.getValue().doInTransaction(null);
    verify(channelsDataService).update(channel);

    verify(eventRelay).sendEventMessage(captor.capture());

    MotechEvent event = captor.getValue();

    assertEquals(CHANNEL_UPDATE_SUBJECT, event.getSubject());
    assertEquals(BUNDLE_SYMBOLIC_NAME, event.getParameters().get(CHANNEL_MODULE_NAME));
  }
  @Test
  public void shouldSendEventWhenChannelWasDeleted() {
    Channel channel = new Channel("displayName", BUNDLE_SYMBOLIC_NAME, VERSION);

    when(channelsDataService.findByModuleName(channel.getModuleName())).thenReturn(channel);
    when(bundleContext.getBundles()).thenReturn(new Bundle[] {bundle});
    when(bundle.getSymbolicName()).thenReturn(BUNDLE_SYMBOLIC_NAME);

    ArgumentCaptor<MotechEvent> captor = ArgumentCaptor.forClass(MotechEvent.class);
    Channel deletedChannel = new Channel("displayName2", BUNDLE_SYMBOLIC_NAME, VERSION);
    channelService.delete(deletedChannel.getModuleName());

    ArgumentCaptor<TransactionCallback> transactionCaptor =
        ArgumentCaptor.forClass(TransactionCallback.class);
    verify(channelsDataService).doInTransaction(transactionCaptor.capture());
    transactionCaptor.getValue().doInTransaction(null);
    verify(channelsDataService).delete(channel);

    verify(eventRelay).sendEventMessage(captor.capture());

    MotechEvent event = captor.getValue();

    assertEquals(CHANNEL_DEREGISTER_SUBJECT, event.getSubject());
    assertEquals(BUNDLE_SYMBOLIC_NAME, event.getParameters().get(CHANNEL_MODULE_NAME));
  }
  @Test
  public void shouldGetChannelByChannelInfo() {
    String displayName = "Test";
    String moduleName = "test-1";

    Channel expected = new Channel();
    expected.setDisplayName(displayName);
    expected.setModuleName(moduleName);
    expected.setModuleVersion(VERSION);

    when(channelsDataService.findByModuleName(moduleName)).thenReturn(expected);

    when(bundleContext.getBundles()).thenReturn(new Bundle[] {bundle});
    when(bundle.getSymbolicName()).thenReturn(moduleName);

    Channel actual = channelService.getChannel(moduleName);

    assertNotNull(actual);
    assertEquals(expected, actual);
  }
  @Test
  public void shouldRegisterChannel() {
    String triggerEvent =
        "{ displayName: 'displayName', subject: 'subject', eventParameters: [{ displayName: 'displayName', eventKey: 'eventKey' }] }";
    String channel =
        String.format(
            "{displayName: %s, triggerTaskEvents: [%s]}", BUNDLE_SYMBOLIC_NAME, triggerEvent);
    InputStream stream = new ByteArrayInputStream(channel.getBytes(Charset.forName("UTF-8")));

    channelService.registerChannel(stream, BUNDLE_SYMBOLIC_NAME, VERSION);

    ArgumentCaptor<TransactionCallback> transactionCaptor =
        ArgumentCaptor.forClass(TransactionCallback.class);
    verify(channelsDataService).doInTransaction(transactionCaptor.capture());
    transactionCaptor.getValue().doInTransaction(null);

    ArgumentCaptor<Channel> captor = ArgumentCaptor.forClass(Channel.class);
    verify(channelsDataService).create(captor.capture());

    Channel c = captor.getValue();

    assertEquals(BUNDLE_SYMBOLIC_NAME, c.getDisplayName());
    assertEquals(BUNDLE_SYMBOLIC_NAME, c.getModuleName());
    assertEquals(VERSION, c.getModuleVersion());
    assertEquals(1, c.getTriggerTaskEvents().size());
    assertEquals(
        new TriggerEvent(
            "displayName",
            "subject",
            null,
            asList(new EventParameter("displayName", "eventKey")),
            ""),
        c.getTriggerTaskEvents().get(0));
  }
  @Test
  public void shouldUnregisterChannel() {
    Channel channel = new Channel("Channel to delete", BUNDLE_SYMBOLIC_NAME, VERSION);

    when(channelsDataService.findByModuleName(channel.getModuleName())).thenReturn(channel);
    when(bundleContext.getBundles()).thenReturn(new Bundle[] {bundle});
    when(bundle.getSymbolicName()).thenReturn(BUNDLE_SYMBOLIC_NAME);

    channelService.unregisterChannel(channel.getModuleName());

    ArgumentCaptor<TransactionCallback> transactionCaptor =
        ArgumentCaptor.forClass(TransactionCallback.class);
    verify(channelsDataService).doInTransaction(transactionCaptor.capture());
    transactionCaptor.getValue().doInTransaction(null);

    ArgumentCaptor<Channel> captor = ArgumentCaptor.forClass(Channel.class);
    verify(channelsDataService).delete(captor.capture());

    Channel deletedChannel = captor.getValue();

    assertEquals("Channel to delete", deletedChannel.getDisplayName());
    assertEquals(BUNDLE_SYMBOLIC_NAME, deletedChannel.getModuleName());
    assertEquals(VERSION, deletedChannel.getModuleVersion());
  }
  @Test
  public void shouldRegisterChannelFromChannelRequest() {
    List<ActionEventRequest> actionEventRequests =
        asList(
            new TestActionEventRequestBuilder()
                .setDisplayName("actionName")
                .setSubject("subject.foo")
                .setDescription("action description")
                .setServiceInterface("some.interface")
                .setServiceMethod("method")
                .setActionParameters(new TreeSet<ActionParameterRequest>())
                .createActionEventRequest());
    List<TriggerEventRequest> triggerEventsRequest =
        asList(
            new TriggerEventRequest(
                "displayName",
                "subject.foo",
                "description",
                asList(new EventParameterRequest("displayName", "eventKey"))));
    ChannelRequest channelRequest =
        new ChannelRequest(
            BUNDLE_SYMBOLIC_NAME,
            BUNDLE_SYMBOLIC_NAME,
            VERSION,
            "",
            triggerEventsRequest,
            actionEventRequests);

    channelService.registerChannel(channelRequest);

    ArgumentCaptor<TransactionCallback> transactionCaptor =
        ArgumentCaptor.forClass(TransactionCallback.class);
    verify(channelsDataService).doInTransaction(transactionCaptor.capture());
    transactionCaptor.getValue().doInTransaction(null);

    ArgumentCaptor<Channel> captor = ArgumentCaptor.forClass(Channel.class);
    verify(channelsDataService).create(captor.capture());

    Channel channelToBeCreated = captor.getValue();

    assertEquals(BUNDLE_SYMBOLIC_NAME, channelToBeCreated.getDisplayName());
    assertEquals(BUNDLE_SYMBOLIC_NAME, channelToBeCreated.getModuleName());
    assertEquals(VERSION, channelToBeCreated.getModuleVersion());

    assertEquals(1, channelToBeCreated.getTriggerTaskEvents().size());
    TriggerEvent expectedTrigger =
        new TriggerEvent(
            "displayName",
            "subject.foo",
            "description",
            asList(new EventParameter("displayName", "eventKey")),
            "");
    TriggerEvent actualTrigger = channelToBeCreated.getTriggerTaskEvents().get(0);
    assertEquals(expectedTrigger, actualTrigger);

    assertEquals(1, channelToBeCreated.getActionTaskEvents().size());
    ActionEvent expectedAction =
        new ActionEventBuilder()
            .setDisplayName("actionName")
            .setSubject("subject.foo")
            .setDescription("action description")
            .setServiceInterface("some.interface")
            .setServiceMethod("method")
            .setActionParameters(new TreeSet<>())
            .build();
    ActionEvent actualAction = channelToBeCreated.getActionTaskEvents().get(0);
    assertEquals(expectedAction, actualAction);
  }