text: const should = require('should');
  const uuid = require('node-uuid');
  
  const {ProcessInstanceHandler, TestFixtureProvider} = require('../../../dist/commonjs/test_setup');
  
  describe('ConsumerAPI:   Receive global IntermediateThrowEvent Notifications', () => {
  
    let eventAggregator;
    let processInstanceHandler;
    let testFixtureProvider;
  
    let defaultIdentity;
  
    const processModelId = 'test_consumer_api_intermediate-throw-event';
  
    let correlationId;
  
    const noopCallback = () => {};
  
    const intermediateThrowEventTriggeredMessagePath = 'intermediate_throw_event_triggered';
    const sampleIntermediateThrowEventMessage = {
      correlationId: uuid.v4(),
      processModelId: 'processModelId',
      processInstanceId: uuid.v4(),
      flowNodeId: 'IntermediateThrowEvent_1',
      flowNodeInstanceId: uuid.v4(),
      processInstanceOwner: undefined, // Can only be set after the TestFixtureProvider was initialized.
      payload: {},
    };
  
    before(async () => {
      testFixtureProvider = new TestFixtureProvider();
      await testFixtureProvider.initializeAndStart();
      defaultIdentity = testFixtureProvider.identities.defaultUser;
  
      sampleIntermediateThrowEventMessage.processInstanceOwner = defaultIdentity;
  
      const processModelsToImport = [processModelId];
      await testFixtureProvider.importProcessFiles(processModelsToImport);
  
      eventAggregator = await testFixtureProvider.resolveAsync('EventAggregator');
      processInstanceHandler = new ProcessInstanceHandler(testFixtureProvider);
    });
  
    after(async () => {
      await testFixtureProvider.tearDown();
    });
  
    it('should send a notification via socket when an IntermediateThrowEvent is triggered', async () => {
  
      correlationId = uuid.v4();
  
      return new Promise(async (resolve, reject) => {
  
        const notificationReceivedCallback = async (intermediateThrowEventTriggeredMessage) => {
  
          should.exist(intermediateThrowEventTriggeredMessage);
  
          const messageIsAboutCorrectIntermediateThrowEvent =
            intermediateThrowEventTriggeredMessage.flowNodeId === sampleIntermediateThrowEventMessage.flowNodeId;
  
          should(messageIsAboutCorrectIntermediateThrowEvent).be.true();
  
          const processInstanceFinished = (() => {
            resolve();
          });
  
          processInstanceHandler.waitForProcessInstanceToEnd(correlationId, processModelId, processInstanceFinished);
        };
  
        const subscribeOnce = true;
        await testFixtureProvider
          .consumerApiClient
          .onIntermediateThrowEventTriggered(defaultIdentity, notificationReceivedCallback, subscribeOnce);
  
        await processInstanceHandler.startProcessInstanceAndReturnCorrelationId(processModelId, correlationId);
      });
    });
  
    it('should fail to subscribe for the IntermediateThrowEventTriggered notification, if the user is unauthorized', async () => {
      try {
        const subscribeOnce = true;
        const subscription = await testFixtureProvider
          .consumerApiClient
          .onIntermediateThrowEventTriggered({}, noopCallback, subscribeOnce);
        should.fail(subscription, undefined, 'This should not have been possible, because the user is unauthorized!');
      } catch (error) {
        const expectedErrorMessage = /no auth token/i;
        const expectedErrorCode = 401;
        should(error.message).be.match(expectedErrorMessage);
        should(error.code).be.match(expectedErrorCode);
      }
    });
  
    it('should fail to subscribe for the IntermediateThrowEventTriggered notification, if the user is unauthorized', async () => {
      try {
        const subscribeOnce = true;
        const subscription = await testFixtureProvider
          .consumerApiClient
          .onIntermediateThrowEventTriggered({}, noopCallback, subscribeOnce);
        should.fail(subscription, undefined, 'This should not have been possible, because the user is unauthorized!');
      } catch (error) {
        const expectedErrorMessage = /no auth token/i;
        const expectedErrorCode = 401;
        should(error.message).be.match(expectedErrorMessage);
        should(error.code).be.match(expectedErrorCode);
      }
    });
  
    it('should no longer receive IntermediateThrowEventTriggered notifications, after the subscription was removed', async () => {
  
      let receivedNotifications = 0;
  
      const notificationReceivedCallback = async (message) => {
        receivedNotifications++;
      };
  
      // Create the subscription
      const subscribeOnce = false;
      const subscription = await testFixtureProvider
        .consumerApiClient
        .onIntermediateThrowEventTriggered(defaultIdentity, notificationReceivedCallback, subscribeOnce);
  
      // Publish the first notification
      eventAggregator.publish(intermediateThrowEventTriggeredMessagePath, sampleIntermediateThrowEventMessage);
  
      // Wait some time before removing the subscription, or we risk it being destroyed
      // before the first notification is received.
      await processInstanceHandler.wait(500);
  
      // Remove the subscription
      await testFixtureProvider
        .consumerApiClient
        .removeSubscription(defaultIdentity, subscription);
  
      // Publish more events
      eventAggregator.publish(intermediateThrowEventTriggeredMessagePath, sampleIntermediateThrowEventMessage);
      eventAggregator.publish(intermediateThrowEventTriggeredMessagePath, sampleIntermediateThrowEventMessage);
  
      const expectedReceivedAmountOfNotifications = 1;
      should(receivedNotifications).be.equal(expectedReceivedAmountOfNotifications);
    });
  
    it('should continuously receive IntermediateThrowEventTriggered notifications, if subscribeOnce is set to "false"', async () => {
  
      return new Promise(async (resolve, reject) => {
        let receivedNotifications = 0;
  
        const notificationReceivedCallback = async (message) => {
          receivedNotifications++;
  
          // If it is confirmed that this subscription is still active
          // after receiving multiple events, this test was successful.
          if (receivedNotifications === 2) {
            await testFixtureProvider
              .consumerApiClient
              .removeSubscription(defaultIdentity, subscription);
  
            resolve();
          }
        };
  
        // Create the subscription
        const subscribeOnce = false;
        const subscription = await testFixtureProvider
          .consumerApiClient
          .onIntermediateThrowEventTriggered(defaultIdentity, notificationReceivedCallback, subscribeOnce);
  
        // Publish a number of events
        eventAggregator.publish(intermediateThrowEventTriggeredMessagePath, sampleIntermediateThrowEventMessage);
        eventAggregator.publish(intermediateThrowEventTriggeredMessagePath, sampleIntermediateThrowEventMessage);
      });
    });
  
    it('should only receive one IntermediateThrowEventTriggered notification, if subscribeOnce is set to "true"', async () => {
      let receivedNotifications = 0;
  
      const notificationReceivedCallback = async (message) => {
        receivedNotifications++;
      };
  
      // Create the subscription
      const subscribeOnce = true;
      await testFixtureProvider
        .consumerApiClient
        .onIntermediateThrowEventTriggered(defaultIdentity, notificationReceivedCallback, subscribeOnce);
  
      // Publish a number of events
      eventAggregator.publish(intermediateThrowEventTriggeredMessagePath, sampleIntermediateThrowEventMessage);
  
      // Wait some time before publishing another event, or we risk the subscription being removed
      // before the first notification is received.
      await processInstanceHandler.wait(500);
  
      eventAggregator.publish(intermediateThrowEventTriggeredMessagePath, sampleIntermediateThrowEventMessage);
  
      const expectedReceivedAmountOfNotifications = 1;
      should(receivedNotifications).be.equal(expectedReceivedAmountOfNotifications);
    });
  });
  