'use strict';

const expect = require('chai').expect;
const AwsCompileWebsocketsEvents = require('../../../../../../../../../../lib/plugins/aws/package/compile/events/websockets/index');
const Serverless = require('../../../../../../../../../../lib/serverless');
const AwsProvider = require('../../../../../../../../../../lib/plugins/aws/provider');

describe('#compileDeployment()', () => {
  let awsCompileWebsocketsEvents;

  beforeEach(() => {
    const options = {
      stage: 'dev',
      region: 'us-east-1',
    };
    const serverless = new Serverless({ commands: [], options: {} });
    serverless.setProvider('aws', new AwsProvider(serverless));
    serverless.service.provider.compiledCloudFormationTemplate = {
      Resources: {},
      Outputs: {},
    };

    awsCompileWebsocketsEvents = new AwsCompileWebsocketsEvents(serverless, options);

    awsCompileWebsocketsEvents.websocketsApiLogicalId =
      awsCompileWebsocketsEvents.provider.naming.getWebsocketsApiLogicalId();
  });

  it('should create a deployment resource and output', () => {
    awsCompileWebsocketsEvents.validated = {
      events: [
        {
          functionName: 'First',
          route: '$connect',
        },
        {
          functionName: 'Second',
          route: '$disconnect',
        },
      ],
    };

    awsCompileWebsocketsEvents.compileDeployment();
    const resources =
      awsCompileWebsocketsEvents.serverless.service.provider.compiledCloudFormationTemplate
        .Resources;
    const outputs =
      awsCompileWebsocketsEvents.serverless.service.provider.compiledCloudFormationTemplate.Outputs;

    const deploymentLogicalId = Object.keys(resources)[0];

    expect(deploymentLogicalId).to.match(/WebsocketsDeployment/);
    expect(resources[deploymentLogicalId]).to.deep.equal({
      Type: 'AWS::ApiGatewayV2::Deployment',
      DependsOn: ['SconnectWebsocketsRoute', 'SdisconnectWebsocketsRoute'],
      Properties: {
        ApiId: {
          Ref: 'WebsocketsApi',
        },
        Description: 'Serverless Websockets',
      },
    });
    expect(outputs).to.deep.equal({
      ServiceEndpointWebsocket: {
        Description: 'URL of the service endpoint',
        Value: {
          'Fn::Join': [
            '',
            [
              'wss://',
              {
                Ref: 'WebsocketsApi',
              },
              '.execute-api.',
              {
                Ref: 'AWS::Region',
              },
              '.',
              {
                Ref: 'AWS::URLSuffix',
              },
              '/dev',
            ],
          ],
        },
      },
    });
  });

  it('should create a deployment resource with stage reference if websocketApiId is specified', () => {
    awsCompileWebsocketsEvents.validated = {
      events: [
        {
          functionName: 'First',
          route: '$connect',
        },
        {
          functionName: 'Second',
          route: '$disconnect',
        },
      ],
    };
    awsCompileWebsocketsEvents.serverless.service.provider.apiGateway = {
      websocketApiId: 'xyz123abc',
    };

    awsCompileWebsocketsEvents.compileDeployment();
    const resources =
      awsCompileWebsocketsEvents.serverless.service.provider.compiledCloudFormationTemplate
        .Resources;

    const deploymentLogicalId = Object.keys(resources)[0];

    expect(deploymentLogicalId).to.match(/WebsocketsDeployment/);
    expect(resources[deploymentLogicalId]).to.deep.equal({
      Type: 'AWS::ApiGatewayV2::Deployment',
      DependsOn: ['SconnectWebsocketsRoute', 'SdisconnectWebsocketsRoute'],
      Properties: {
        ApiId: 'xyz123abc',
        StageName: awsCompileWebsocketsEvents.provider.getStage(),
        Description: 'Serverless Websockets',
      },
    });
  });

  it('should add deployment logical id to stage if no websocketApiId specified', async () => {
    awsCompileWebsocketsEvents.validated = {
      events: [
        {
          functionName: 'First',
          route: '$connect',
        },
        {
          functionName: 'Second',
          route: '$disconnect',
        },
      ],
    };

    return awsCompileWebsocketsEvents.compileStage().then(() => {
      awsCompileWebsocketsEvents.compileDeployment();
      const resources =
        awsCompileWebsocketsEvents.serverless.service.provider.compiledCloudFormationTemplate
          .Resources;

      expect(resources.WebsocketsDeploymentStage.Properties.DeploymentId).to.deep.equal({
        Ref: awsCompileWebsocketsEvents.websocketsDeploymentLogicalId,
      });
    });
  });
});
