Skip to content

Tests do not enforce the Pipeline interface contract; invalid keys are serialised into YAML #21

Description

@neilherbertuk

While working on my PR, I noticed an issue that significantly reduces the effectiveness of the current test suite, particularly given that this is a Typescript package.

At a high level: the tests validate string output, but they do not validate that the input object actually conforms to the intended Pipeline interface shape.

Example

Using the existing minimal pipeline test as a base, lets add a keyword that is not part of the interface. I've added one to globalKeywords :

test('minimal pipeline', () => {
  const minimalPipeline: Pipeline = {
    globalKeywords: {
      workflow: {
        name: 'Minimal Pipeline',
      },
      totallyInvalidKey: {
        anotherInvalidKey: 'Invalid Key Value'
      },
    },
    jobs: {},
  };

  equal(toYAML(minimalPipeline), readFileSync('./test/minimalPipeline.yaml', 'utf8'));
});

My IDE correctly identifies this as invalid;

Image

When this test runs, I would expect the input to cause a compile time / type error as it does not conform to the Pipeline interface. In reality, the test fails but not because of this, it is because the totallyInvalidKey has been silently added to the output, which the snapshot it is being compared to does not include.

Image

Updating the yaml snapshot results in the test passing:

workflow:
  name: Minimal Pipeline
totallyInvalidKey:
  anotherInvalidKey: Invalid Key Value
Image

My understanding is that the built-in node test runner (node:test) has no knowledge of Typescript so the interfaces and types are being ignored.

I would like to suggest that the package switches to using jest with ts-jest.

Migrating the above test to jest:

import { readFileSync } from 'node:fs';
import { Pipeline, toYAML } from '../src/index.ts';

describe('minimal pipeline', () => {
  it('should output valid yaml', () => {
    const minimalPipeline: Pipeline = {
      globalKeywords: {
        workflow: {
          name: 'Minimal Pipeline',
        },
        totallyInvalidKey: {
          anotherInvalidKey: 'Invalid Key Value'
        },
      },
      jobs: {},
    };

    expect(toYAML(minimalPipeline)).toEqual(readFileSync('./test/minimalPipeline.yaml', 'utf8'));
  });
});

Running jest against this results in:

Image

Removing the invalid key and reverting the snapshot allows the test to pass:

Image

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions