Skip to content

Commit

Permalink
Merge pull request #618 from JupiterOne/add-type-to-jest-matcher
Browse files Browse the repository at this point in the history
Add type to jest matcher
  • Loading branch information
ndowmon authored Feb 15, 2022
2 parents cf35d92 + 0b5ba19 commit ae7f316
Show file tree
Hide file tree
Showing 3 changed files with 137 additions and 10 deletions.
16 changes: 16 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,22 @@ and this project adheres to

### Added

- Updated jest matchers in the following way:

- added optional `_type` argument to `.toMatchGraphObjectSchema` matcher
- added optional `_type` and `_class` arguments to
`.toMatchDirectRelationshipSchema` matcher

This enables developers to simply pass the `StepEntityMetadata` and
`StepRelationshipMetadata` interfaces to these matchers. Usage:

```ts
expect(collectedEntities).toMatchGraphObjectSchema(Entities.USER);
expect(collectedRelationships).toMatchDirectRelationshipSchema(
Relationships.ACCOUNT_HAS_USER,
);
```

- Added optional `schema` property to `StepGraphObjectMetadata`. This allows
developers to provide the property schema to expect on entities,
relationships, and mapped relationships. This serves two uses:
Expand Down
91 changes: 91 additions & 0 deletions packages/integration-sdk-testing/src/__tests__/jest.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,35 @@ describe('#toMatchGraphObjectSchema', () => {
expect(result.message()).toEqual('Success!');
});

test('should require matching `_type` if `_type` is provided', () => {
const entity = generateCollectedEntity({
_class: 'Service',
_type: 'entity-type',
});

const result = toMatchGraphObjectSchema(entity, {
_class: entity._class,
_type: 'different-entity-type',
});

expect(result).toEqual({
message: expect.any(Function),
pass: false,
});

expect(result.message()).toMatch(`errors=[
{
"instancePath": "/_type",
"schemaPath": "#/properties/_type/const",
"keyword": "const",
"params": {
"allowedValue": "different-entity-type"
},
"message": "must be equal to constant"
}
]`);
});

test('should match class schema with no custom schema', () => {
const result = toMatchGraphObjectSchema(
generateCollectedEntity({ _class: 'Service' }),
Expand Down Expand Up @@ -597,6 +626,68 @@ Find out more about JupiterOne schemas: https://github.com/JupiterOne/data-model
Find out more about JupiterOne schemas: https://github.com/JupiterOne/data-model/tree/main/src/schemas
`);
});

test('should require matching `_type` if `_type` is provided', () => {
const relationship = generateCollectedDirectRelationship({
string: 'abc',
number: 123,
boolean: true,
null: null,
_type: 'relationship-type',
});

const result = toMatchDirectRelationshipSchema(relationship, {
_type: 'different-relationship-type',
});

expect(result).toEqual({
message: expect.any(Function),
pass: false,
});

expect(result.message()).toMatch(`errors=[
{
"instancePath": "/_type",
"schemaPath": "#/properties/_type/const",
"keyword": "const",
"params": {
"allowedValue": "different-relationship-type"
},
"message": "must be equal to constant"
}
]`);
});

test('should require matching `_class` if `_class` is provided', () => {
const relationship = generateCollectedDirectRelationship({
string: 'abc',
number: 123,
boolean: true,
null: null,
_class: RelationshipClass.HAS,
});

const result = toMatchDirectRelationshipSchema(relationship, {
_class: RelationshipClass.IS,
});

expect(result).toEqual({
message: expect.any(Function),
pass: false,
});

expect(result.message()).toMatch(`errors=[
{
"instancePath": "/_class",
"schemaPath": "#/properties/_class/const",
"keyword": "const",
"params": {
"allowedValue": "IS"
},
"message": "must be equal to constant"
}
]`);
});
});

describe('#toTargetEntities', () => {
Expand Down
40 changes: 30 additions & 10 deletions packages/integration-sdk-testing/src/jest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
IntegrationSpecConfig,
IntegrationStepExecutionContext,
MappedRelationship,
RelationshipClass,
Step,
} from '@jupiterone/integration-sdk-core';
import { getMatchers } from 'expect/build/jestMatchersObject';
Expand All @@ -22,7 +23,7 @@ declare global {
): R;

toMatchDirectRelationshipSchema<T extends ExplicitRelationship>(
params: ToMatchRelationshipSchemaParams,
params?: ToMatchRelationshipSchemaParams,
): R;

toTargetEntities(entities: Entity[]): R;
Expand Down Expand Up @@ -228,6 +229,7 @@ export interface ToMatchGraphObjectSchemaParams {
* The JupiterOne hierarchy class or classes from the data model that will be used to generate a new schema to be validated against. See: https://github.com/JupiterOne/data-model/tree/main/src/schemas
*/
_class: string | string[];
_type?: string;
/**
* The schema that should be used to validate the input data against
*/
Expand Down Expand Up @@ -304,7 +306,7 @@ export function toMatchGraphObjectSchema<T extends Entity>(
* The data received from the test assertion. (e.g. expect(DATA_HERE).toMatchGraphObjectSchema(...)
*/
received: T | T[],
{ _class, schema, disableClassMatch }: ToMatchGraphObjectSchemaParams,
{ _class, _type, schema, disableClassMatch }: ToMatchGraphObjectSchemaParams,
) {
// Copy this so that we do not interfere with globals.
// NOTE: The data-model should actuall expose a function for generating
Expand Down Expand Up @@ -346,12 +348,17 @@ export function toMatchGraphObjectSchema<T extends Entity>(
newEntitySchema.properties._class = {
const: _class,
};
if (_type) {
newEntitySchema.properties._type = { const: _type };
}
}

return toMatchSchema(received, newEntitySchema);
}

export interface ToMatchRelationshipSchemaParams {
_class?: RelationshipClass;
_type?: string;
/**
* The schema that should be used to validate the input data against
*/
Expand Down Expand Up @@ -394,14 +401,27 @@ export function toMatchDirectRelationshipSchema<T extends ExplicitRelationship>(
],
};

return toMatchSchema(
received,
generateGraphObjectSchemaFromDataModelSchemas([
...graphObjectSchemas.reverse(),
directRelationshipSchema,
schema,
]),
);
const newRelationshipSchema = generateGraphObjectSchemaFromDataModelSchemas([
...graphObjectSchemas.reverse(),
directRelationshipSchema,
schema,
]);

if (params?._class) {
if (!newRelationshipSchema.properties) {
newRelationshipSchema.properties = {};
}
newRelationshipSchema.properties._class = { const: params._class };
}

if (params?._type) {
if (!newRelationshipSchema.properties) {
newRelationshipSchema.properties = {};
}
newRelationshipSchema.properties._type = { const: params._type };
}

return toMatchSchema(received, newRelationshipSchema);
}

function toMatchSchema<T extends Entity | ExplicitRelationship>(
Expand Down

0 comments on commit ae7f316

Please sign in to comment.