INTO-CPS-Association/DTaaS

View on GitHub
client/test/preview/unit/util/digitalTwinConfig.test.ts

Summary

Maintainability
A
3 hrs
Test Coverage
import GitlabInstance from 'preview/util/gitlab';
import DigitalTwin from 'preview/util/digitalTwin';

const mockApi = {
  RepositoryFiles: {
    show: jest.fn(),
    remove: jest.fn(),
    edit: jest.fn(),
  },
  Repositories: {
    allRepositoryTrees: jest.fn(),
  },
  PipelineTriggerTokens: {
    trigger: jest.fn(),
  },
  Pipelines: {
    cancel: jest.fn(),
  },
};

const mockGitlabInstance = {
  api: mockApi as unknown as GitlabInstance['api'],
  projectId: 1,
  triggerToken: 'test-token',
  logs: [] as { jobName: string; log: string }[],
  getProjectId: jest.fn(),
  getTriggerToken: jest.fn(),
} as unknown as GitlabInstance;

describe('DigitalTwin', () => {
  let dt: DigitalTwin;

  const mockResponse = [
    { type: 'blob', name: 'file1.md', path: 'test-path' },
    { type: 'blob', name: 'file2.json', path: 'test-path' },
    { type: 'blob', name: 'file3', path: '/lifecycle/test-path' },
    { type: 'tree', name: 'folder', path: 'test-path' },
  ];

  const mockFetchFilesError = async (
    errorMessage: string,
    fetchMethod: () => Promise<void>,
    resultArray: string[],
  ) => {
    (mockApi.Repositories.allRepositoryTrees as jest.Mock).mockRejectedValue(
      new Error(errorMessage),
    );
    await fetchMethod();
    expect(resultArray).toEqual([]);
  };

  const expectAllRepositoryTreesCalled = (
    recursive: boolean,
    lifecycle?: boolean,
  ) => {
    const path = lifecycle
      ? 'digital_twins/test-DTName/lifecycle'
      : 'digital_twins/test-DTName';

    expect(mockApi.Repositories.allRepositoryTrees).toHaveBeenCalledWith(1, {
      path,
      recursive,
    });
  };

  beforeEach(() => {
    mockGitlabInstance.projectId = 1;
    dt = new DigitalTwin('test-DTName', mockGitlabInstance);

    (mockApi.Repositories.allRepositoryTrees as jest.Mock).mockResolvedValue(
      mockResponse,
    );
  });

  it('should get description files', async () => {
    await dt.getDescriptionFiles();

    expectAllRepositoryTreesCalled(false);

    expect(dt.descriptionFiles).toEqual(['file1.md']);
  });

  it('should return empty array when fetching description files fails', async () => {
    await mockFetchFilesError(
      'Error fetching description files',
      dt.getDescriptionFiles.bind(dt),
      dt.descriptionFiles,
    );
  });

  it('should get lifecycle files', async () => {
    await dt.getLifecycleFiles();

    expectAllRepositoryTreesCalled(true, true);

    expect(dt.lifecycleFiles).toEqual(['file3']);
  });

  it('should return empty array when fetching lifecycle files fails', async () => {
    await mockFetchFilesError(
      'Error fetching lifecycle files',
      dt.getLifecycleFiles.bind(dt),
      dt.lifecycleFiles,
    );
  });

  it('should get config files', async () => {
    await dt.getConfigFiles();

    expectAllRepositoryTreesCalled(false);

    expect(dt.configFiles).toEqual(['file2.json']);
  });

  it('should return empty array when fetching config files fails', async () => {
    await mockFetchFilesError(
      'Error fetching config files',
      dt.getConfigFiles.bind(dt),
      dt.configFiles,
    );
  });

  it('should get file content for a file with an extension', async () => {
    const mockContent = btoa('Test file content');
    (mockApi.RepositoryFiles.show as jest.Mock).mockResolvedValue({
      content: mockContent,
    });

    const content = await dt.DTAssets.getFileContent('test-file.md');

    expect(content).toBe('Test file content');
    expect(mockApi.RepositoryFiles.show).toHaveBeenCalledWith(
      1,
      'digital_twins/test-DTName/test-file.md',
      'main',
    );
  });

  it('should get file content for a file without an extension (lifecycle folder)', async () => {
    const mockContent = btoa('Test lifecycle content');
    (mockApi.RepositoryFiles.show as jest.Mock).mockResolvedValue({
      content: mockContent,
    });

    const content = await dt.DTAssets.getFileContent('lifecycle-file');

    expect(content).toBe('Test lifecycle content');
    expect(mockApi.RepositoryFiles.show).toHaveBeenCalledWith(
      1,
      'digital_twins/test-DTName/lifecycle/lifecycle-file',
      'main',
    );
  });

  it('should update file content for a file with an extension', async () => {
    const mockEdit = jest.fn();
    mockApi.RepositoryFiles.edit = mockEdit;

    await dt.DTAssets.updateFileContent('test-file.md', 'Test file content');

    expect(mockApi.RepositoryFiles.edit).toHaveBeenCalledWith(
      1,
      'digital_twins/test-DTName/test-file.md',
      'main',
      'Test file content',
      'Update test-file.md content',
    );
  });

  it('should update file content for a file without an extension (lifecycle folder)', async () => {
    const mockEdit = jest.fn();
    mockApi.RepositoryFiles.edit = mockEdit;

    await dt.DTAssets.updateFileContent(
      'lifecycle-file',
      'Lifecycle file content',
    );

    expect(mockApi.RepositoryFiles.edit).toHaveBeenCalledWith(
      1,
      'digital_twins/test-DTName/lifecycle/lifecycle-file',
      'main',
      'Lifecycle file content',
      'Update lifecycle-file content',
    );
  });
});