feat(codegen:test): coverage x-expanded-relation + x-codegen.queryParams (#3675)

## What

Adding tests to cover `x-expanded-relation` and  `x-codegen.queryParams` handling

## Why

The logic that processes these OAS extension can be complex to reason with. Therefore, we should have automated tests to prevent unintentional regression.

## How

* Focus on `getModels` method and its sub-routines.
* Add coverage to getOperation codegen parsing.
* Add coverage to model and operation spec property.
This commit is contained in:
Patrick
2023-04-05 14:01:29 +00:00
committed by GitHub
parent dd1e86b0d4
commit 0b3c6fde30
15 changed files with 900 additions and 49 deletions
+5
View File
@@ -0,0 +1,5 @@
---
"@medusajs/openapi-typescript-codegen": patch
---
feat(codegen:test): coverage x-expanded-relation + x-codegen.queryParams
@@ -0,0 +1,14 @@
module.exports = {
globals: {
"ts-jest": {
tsConfig: "tsconfig.json",
isolatedModules: false,
},
},
transform: {
"^.+\\.[jt]s?$": "ts-jest",
},
testEnvironment: `node`,
moduleFileExtensions: [`js`, `ts`],
testTimeout: 30000,
}
@@ -22,7 +22,7 @@
"prepare": "cross-env NODE_ENV=production yarn run release",
"build": "rollup --config --environment NODE_ENV:development",
"release": "rollup --config --environment NODE_ENV:production",
"test": "jest --passWithNoTests"
"test": "jest src"
},
"dependencies": {
"camelcase": "^6.3.0",
@@ -49,12 +49,12 @@
"abort-controller": "3.0.0",
"axios": "1.2.0",
"form-data": "4.0.0",
"jest": "26.6.3",
"jest-cli": "26.6.3",
"jest": "^25.5.4",
"node-fetch": "2.6.7",
"qs": "6.10.3",
"rollup": "3.9.1",
"rollup-plugin-terser": "7.0.2",
"ts-jest": "^25.5.1",
"tslib": "2.3.1",
"typescript": "4.9.5"
}
@@ -5,7 +5,7 @@ import type { OpenApiResponse } from "./OpenApiResponse"
* https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.2.md#responsesObject
*/
export interface OpenApiResponses extends OpenApiReference {
default: OpenApiResponse
default?: OpenApiResponse
[httpcode: string]: OpenApiResponse
}
@@ -0,0 +1,52 @@
import { getModel } from "../getModel"
import { OpenApi } from "../../interfaces/OpenApi"
import { Model } from "../../../../client/interfaces/Model"
import { OpenApiSchema } from "../../interfaces/OpenApiSchema"
describe("getModel", () => {
let openApi: OpenApi
beforeEach(async () => {
openApi = {
openapi: "3.0.0",
info: {
title: "Test",
version: "1.0.0",
},
paths: {},
components: {},
}
})
it("should set model spec with definition", () => {
const modelName = "OrderRes"
const definition: OpenApiSchema = {
type: "object",
properties: {
id: {
type: "string",
},
},
}
const model: Model = getModel(openApi, definition, true, modelName)
expect(model.spec).toEqual(definition)
})
it("should set property spec with definition", () => {
const modelName = "OrderRes"
const definition: OpenApiSchema = {
type: "object",
properties: {
order: {
type: "object",
properties: {
id: {
type: "string",
},
},
},
},
}
const model: Model = getModel(openApi, definition, true, modelName)
expect(model.properties[0].spec).toEqual(definition.properties!.order)
})
})
@@ -0,0 +1,169 @@
import { getModels } from "../getModels"
import { OpenApi } from "../../interfaces/OpenApi"
describe("getModels", () => {
let openApi: OpenApi
beforeEach(async () => {
openApi = {
openapi: "3.0.0",
info: {
title: "Test",
version: "1.0.0",
},
paths: {},
components: {},
}
})
it("should return an empty array if no models are found", () => {
const models = getModels(openApi)
expect(models).toEqual([])
})
it("should return an array of models", () => {
openApi.components = {
schemas: {
OrderRes: {
type: "object",
properties: {
id: {
type: "string",
},
},
},
},
}
const models = getModels(openApi)
expect(models).toEqual(
expect.arrayContaining([
expect.objectContaining({
name: "OrderRes",
properties: expect.arrayContaining([
expect.objectContaining({
name: "id",
type: "string",
}),
]),
}),
])
)
})
it("should return an array of models with expanded relations", () => {
openApi.components = {
schemas: {
OrderRes: {
type: "object",
"x-expanded-relations": {
field: "order",
relations: ["region", "region.country"],
},
properties: {
order: {
$ref: "#/components/schemas/Order",
},
},
},
Order: {
type: "object",
properties: {
region: {
$ref: "#/components/schemas/Region",
},
},
},
Region: {
type: "object",
properties: {
country: {
$ref: "#/components/schemas/Country",
},
},
},
Country: {
type: "object",
},
},
}
const models = getModels(openApi)
expect(models).toEqual(
expect.arrayContaining([
expect.objectContaining({
name: "OrderRes",
properties: expect.arrayContaining([
expect.objectContaining({
name: "order",
base: "Order",
nestedRelations: expect.arrayContaining([
expect.objectContaining({
base: "Order",
field: "order",
nestedRelations: expect.arrayContaining([
expect.objectContaining({
field: "region",
base: "Region",
nestedRelations: expect.arrayContaining([
expect.objectContaining({
base: "Country",
field: "country",
nestedRelations: [],
}),
]),
}),
]),
}),
]),
}),
]),
}),
])
)
})
it("should convert query parameters into a schema when x-codegen.queryParams is declared", () => {
openApi.paths = {
"/": {
get: {
operationId: "GetOrder",
"x-codegen": {
queryParams: "GetOrderQueryParams",
},
parameters: [
{
description: "Limit the number of results",
in: "query",
name: "limit",
schema: {
type: "integer",
},
required: true,
deprecated: true,
},
],
responses: {
"200": {
description: "OK",
},
},
},
},
}
const models = getModels(openApi)
expect(models).toEqual(
expect.arrayContaining([
expect.objectContaining({
name: "GetOrderQueryParams",
properties: expect.arrayContaining([
expect.objectContaining({
description: "Limit the number of results",
name: "limit",
type: "number",
isRequired: true,
deprecated: true,
}),
]),
}),
])
)
})
})
@@ -0,0 +1,436 @@
import { Model } from "../../../../client/interfaces/Model"
import { handleExpandedRelations } from "../getModelsExpandedRelations"
import { getModel } from "../getModel"
import { OpenApi } from "../../interfaces/OpenApi"
import { OpenApiSchema } from "../../interfaces/OpenApiSchema"
import { getType } from "../getType"
function getModelsTest(openApi: OpenApi): Model[] {
const models: Model[] = []
if (openApi.components) {
for (const definitionName in openApi.components.schemas) {
if (openApi.components.schemas.hasOwnProperty(definitionName)) {
const definition = openApi.components.schemas[definitionName]
const definitionType = getType(definitionName)
const model = getModel(openApi, definition, true, definitionType.base)
models.push(model)
}
}
}
return models
}
describe("getModelsExpandedRelations", () => {
let openApi: OpenApi
beforeEach(async () => {
openApi = {
openapi: "3.0.0",
info: {
title: "Test",
version: "1.0.0",
},
paths: {},
components: {
schemas: {
Order: {
type: "object",
properties: {
region: {
$ref: "#/components/schemas/Region",
},
total: {
type: "number",
},
},
},
Region: {
type: "object",
properties: {
country: {
$ref: "#/components/schemas/Country",
},
},
},
Country: {
type: "object",
},
Customer: {
type: "object",
properties: {
orders: {
type: "array",
items: {
$ref: "#/components/schemas/Order",
},
},
},
},
},
},
}
})
describe("basic use cases", () => {
it("should find nested relation - model", () => {
const modelName: string = "OrderRes"
const definition: OpenApiSchema = {
type: "object",
"x-expanded-relations": {
field: "order",
relations: ["region"],
},
properties: {
order: {
$ref: "#/components/schemas/Order",
},
},
}
const model: Model = getModel(openApi, definition, true, modelName)
const models: Model[] = [...getModelsTest(openApi), model]
handleExpandedRelations(model, models)
expect(model.properties[0].nestedRelations).toEqual(
expect.arrayContaining([
expect.objectContaining({
field: "order",
base: "Order",
isArray: false,
nestedRelations: expect.arrayContaining([
expect.objectContaining({
field: "region",
base: "Region",
isArray: false,
nestedRelations: [],
}),
]),
}),
])
)
})
it("should find nested relation - shallow", () => {
const modelName: string = "OrderRes"
const definition: OpenApiSchema = {
type: "object",
"x-expanded-relations": {
field: "order",
relations: ["total"],
},
properties: {
order: {
$ref: "#/components/schemas/Order",
},
},
}
const model: Model = getModel(openApi, definition, true, modelName)
const models: Model[] = [...getModelsTest(openApi), model]
handleExpandedRelations(model, models)
expect(model.properties[0].nestedRelations).toEqual(
expect.arrayContaining([
expect.objectContaining({
field: "order",
base: "Order",
isArray: false,
nestedRelations: expect.arrayContaining([
expect.objectContaining({
field: "total",
nestedRelations: [],
}),
]),
}),
])
)
})
it("should find nested relation - array", () => {
const modelName: string = "CustomerRes"
const definition: OpenApiSchema = {
type: "object",
"x-expanded-relations": {
field: "customer",
relations: ["orders"],
},
properties: {
customer: {
$ref: "#/components/schemas/Customer",
},
},
}
const model: Model = getModel(openApi, definition, true, modelName)
const models: Model[] = [...getModelsTest(openApi), model]
handleExpandedRelations(model, models)
expect(model.properties[0].nestedRelations).toEqual(
expect.arrayContaining([
expect.objectContaining({
field: "customer",
base: "Customer",
isArray: false,
nestedRelations: expect.arrayContaining([
expect.objectContaining({
field: "orders",
base: "Order",
isArray: true,
nestedRelations: [],
}),
]),
}),
])
)
})
})
describe("misc usage", () => {
it.each([["allOf"], ["anyOf"], ["oneOf"]])(
"should findPropInCombination - %s",
(combination) => {
openApi.components!.schemas!.ExpandedOrder = {
[combination]: [{ $ref: "#/components/schemas/Order" }],
}
const modelName: string = "OrderRes"
const definition: OpenApiSchema = {
type: "object",
"x-expanded-relations": {
field: "order",
relations: ["region"],
},
properties: {
order: {
$ref: "#/components/schemas/ExpandedOrder",
},
},
}
const model: Model = getModel(openApi, definition, true, modelName)
const models: Model[] = [...getModelsTest(openApi), model]
handleExpandedRelations(model, models)
expect(model.properties[0].nestedRelations).toEqual(
expect.arrayContaining([
expect.objectContaining({
nestedRelations: expect.arrayContaining([
expect.objectContaining({
field: "region",
}),
]),
}),
])
)
}
)
it.each([["relations"], ["totals"], ["implicit"], ["eager"]])(
"should find nested relation with relation type - %s",
(relationType) => {
const modelName: string = "OrderRes"
const definition: OpenApiSchema = {
type: "object",
"x-expanded-relations": {
field: "order",
[relationType]: ["region"],
},
properties: {
order: {
$ref: "#/components/schemas/Order",
},
},
}
const model: Model = getModel(openApi, definition, true, modelName)
const models: Model[] = [...getModelsTest(openApi), model]
handleExpandedRelations(model, models)
expect(model.properties[0].nestedRelations).toEqual(
expect.arrayContaining([
expect.objectContaining({
nestedRelations: expect.arrayContaining([
expect.objectContaining({
field: "region",
}),
]),
}),
])
)
}
)
it("should set field hasDepth - true", () => {
const modelName: string = "OrderRes"
const definition: OpenApiSchema = {
type: "object",
"x-expanded-relations": {
field: "order",
relations: ["region.country"],
},
properties: {
order: {
$ref: "#/components/schemas/Order",
},
},
}
const model: Model = getModel(openApi, definition, true, modelName)
const models: Model[] = [...getModelsTest(openApi), model]
handleExpandedRelations(model, models)
expect(model.properties[0].nestedRelations).toEqual(
expect.arrayContaining([
expect.objectContaining({
hasDepth: true,
nestedRelations: expect.arrayContaining([
expect.objectContaining({
field: "region",
nestedRelations: expect.arrayContaining([
expect.objectContaining({
field: "country",
}),
]),
}),
]),
}),
])
)
})
it("should set relation hasDepth - true", () => {
const modelName: string = "CustomerRes"
const definition: OpenApiSchema = {
type: "object",
"x-expanded-relations": {
field: "customer",
relations: ["orders.region.country"],
},
properties: {
customer: {
$ref: "#/components/schemas/Customer",
},
},
}
const model: Model = getModel(openApi, definition, true, modelName)
const models: Model[] = [...getModelsTest(openApi), model]
handleExpandedRelations(model, models)
expect(model.properties[0].nestedRelations).toEqual(
expect.arrayContaining([
expect.objectContaining({
hasDepth: true,
nestedRelations: expect.arrayContaining([
expect.objectContaining({
field: "orders",
hasDepth: true,
nestedRelations: expect.arrayContaining([
expect.objectContaining({
field: "region",
nestedRelations: expect.arrayContaining([
expect.objectContaining({
field: "country",
nestedRelations: [],
}),
]),
}),
]),
}),
]),
}),
])
)
})
it("should add models with relation to root model imports, only once", () => {
const modelName: string = "OrderRes"
const definition: OpenApiSchema = {
type: "object",
"x-expanded-relations": {
field: "order",
relations: ["region", "region.country"],
},
properties: {
order: {
$ref: "#/components/schemas/Order",
},
},
}
const model: Model = getModel(openApi, definition, true, modelName)
const models: Model[] = [...getModelsTest(openApi), model]
handleExpandedRelations(model, models)
expect(model.imports).toEqual(expect.arrayContaining(["Order", "Region"]))
})
})
describe("errors", () => {
it("should throw if field is not found", () => {
const modelName: string = "OrderRes"
const definition: OpenApiSchema = {
type: "object",
"x-expanded-relations": {
field: "nope",
},
properties: {
order: {
$ref: "#/components/schemas/Order",
},
},
}
const model: Model = getModel(openApi, definition, true, modelName)
const models: Model[] = [...getModelsTest(openApi), model]
expect(() => handleExpandedRelations(model, models)).toThrow(
"x-expanded-relations - field not found"
)
})
it("should throw if relation is not found", () => {
const modelName: string = "OrderRes"
const definition: OpenApiSchema = {
type: "object",
"x-expanded-relations": {
field: "order",
relations: ["nope"],
},
properties: {
order: {
$ref: "#/components/schemas/Order",
},
},
}
const model: Model = getModel(openApi, definition, true, modelName)
const models: Model[] = [...getModelsTest(openApi), model]
expect(() => handleExpandedRelations(model, models)).toThrow(
"x-expanded-relations - relation not found"
)
})
it.each([["allOf"], ["anyOf"], ["oneOf"]])(
"should throw if field exports as a combination - %s",
(combination) => {
const modelName: string = "OrderRes"
const definition: OpenApiSchema = {
type: "object",
"x-expanded-relations": {
field: "order",
relations: ["region"],
},
properties: {
order: {
[combination]: [{ $ref: "#/components/schemas/Order" }],
},
},
}
const model: Model = getModel(openApi, definition, true, modelName)
const models: Model[] = [...getModelsTest(openApi), model]
expect(() => handleExpandedRelations(model, models)).toThrow(
"x-expanded-relations - unsupported - field referencing multiple models"
)
}
)
})
})
@@ -0,0 +1,71 @@
import { OpenApi } from "../../interfaces/OpenApi"
import { OpenApiOperation } from "../../interfaces/OpenApiOperation"
import { getOperation } from "../getOperation"
import { getOperationParameters } from "../getOperationParameters"
describe("getOperation", () => {
let openApi: OpenApi
beforeEach(async () => {
openApi = {
openapi: "3.0.0",
info: {
title: "Test",
version: "1.0.0",
},
paths: {},
components: {},
}
})
it("should parse x-codegen", () => {
const op: OpenApiOperation = {
"x-codegen": {
method: "list",
},
responses: {
"200": {
description: "OK",
},
},
}
const pathParams = getOperationParameters(openApi, [])
const operation = getOperation(
openApi,
"/orders",
"get",
"Orders",
op,
pathParams
)
expect(operation).toEqual(
expect.objectContaining({
codegen: { method: "list" },
})
)
})
it("should add x-codegen.queryParams to imports", () => {
const op: OpenApiOperation = {
"x-codegen": {
queryParams: "OrdersQueryParams",
},
responses: {
"200": {
description: "OK",
},
},
}
const pathParams = getOperationParameters(openApi, [])
const operation = getOperation(
openApi,
"/orders",
"get",
"Orders",
op,
pathParams
)
expect(operation.imports).toEqual(
expect.arrayContaining(["OrdersQueryParams"])
)
})
})
@@ -0,0 +1,27 @@
import { OpenApi } from "../../interfaces/OpenApi"
import { getOperationParameter } from "../getOperationParameter"
import { OpenApiParameter } from "../../interfaces/OpenApiParameter"
describe("getOperation", () => {
let openApi: OpenApi
beforeEach(async () => {
openApi = {
openapi: "3.0.0",
info: {
title: "Test",
version: "1.0.0",
},
paths: {},
components: {},
}
})
it("should set spec with definition", () => {
const parameter: OpenApiParameter = {
name: "id",
in: "path",
}
const operationParameter = getOperationParameter(openApi, parameter)
expect(operationParameter.spec).toEqual(parameter)
})
})
@@ -0,0 +1,37 @@
import { OpenApi } from "../../interfaces/OpenApi"
import { getOperationRequestBody } from "../getOperationRequestBody"
import { OpenApiRequestBody } from "../../interfaces/OpenApiRequestBody"
describe("getOperation", () => {
let openApi: OpenApi
beforeEach(async () => {
openApi = {
openapi: "3.0.0",
info: {
title: "Test",
version: "1.0.0",
},
paths: {},
components: {},
}
})
it("should set spec with definition", () => {
const body: OpenApiRequestBody = {
content: {
"application/json": {
schema: {
type: "object",
properties: {
id: {
type: "string",
},
},
},
},
},
}
const operationRequestBody = getOperationRequestBody(openApi, body)
expect(operationRequestBody.spec).toEqual(body)
})
})
@@ -0,0 +1,26 @@
import { OpenApi } from "../../interfaces/OpenApi"
import { getOperationResponse } from "../getOperationResponse"
import { OpenApiResponse } from "../../interfaces/OpenApiResponse"
describe("getOperation", () => {
let openApi: OpenApi
beforeEach(async () => {
openApi = {
openapi: "3.0.0",
info: {
title: "Test",
version: "1.0.0",
},
paths: {},
components: {},
}
})
it("should set spec with definition", () => {
const response: OpenApiResponse = {
description: "OK",
}
const operationResponse = getOperationResponse(openApi, response, 200)
expect(operationResponse.spec).toEqual(response)
})
})
@@ -38,7 +38,7 @@ export const getModelProperties = (
| "enums"
| "properties"
> = {
spec: definition,
spec: property,
name: escapeName(propertyName),
description: property.description || null,
deprecated: property.deprecated === true,
@@ -21,16 +21,21 @@ export const handleExpandedRelations = (model: Model, allModels: Model[]) => {
walkSplitRelations(nestedRelation, splitRelation, 0)
}
walkNestedRelations(allModels, model, model, nestedRelation)
model.imports = [...new Set(model.imports)]
const prop = getPropertyByName(nestedRelation.field, model)
if (!prop) {
throw new Error(`x-expanded-relations error - field not found
throw new Error(`x-expanded-relations - field not found
Schema: ${model.name}
NestedRelation: ${JSON.stringify(nestedRelation, null, 2)}
Model: ${JSON.stringify(model.spec, null, 2)}`)
}
walkNestedRelations(allModels, model, model, nestedRelation)
model.imports = [...new Set(model.imports)]
/**
* To reduce complexity in the exportInterface template, nestedRelations is
* set on the property that is the root of the nested relations instead of
* setting it on the model.
*/
prop.nestedRelations = [nestedRelation]
}
@@ -63,17 +68,21 @@ const walkNestedRelations = (
model: Model,
nestedRelation: NestedRelation,
parentNestedRelation?: NestedRelation
) => {
): void => {
const prop = ["all-of", "any-of", "one-of"].includes(model.export)
? findPropInCombination(nestedRelation.field, model, allModels)
: getPropertyByName(nestedRelation.field, model)
if (!prop) {
throw new Error(`x-expanded-relations - field not found
throw new Error(`x-expanded-relations - relation not found
Schema: ${rootModel.name}
NestedRelation: ${JSON.stringify(nestedRelation, null, 2)}
Model: ${JSON.stringify(model.spec, null, 2)}`)
}
if (["all-of", "any-of", "one-of"].includes(prop.export)) {
/**
* Root property for nested relations can not use combination strategies.
* To use combination, they must be defined in referenced models instead.
*/
throw new Error(`x-expanded-relations - unsupported - field referencing multiple models
Schema: ${rootModel.name}
NestedRelation: ${JSON.stringify(nestedRelation, null, 2)}
@@ -0,0 +1,5 @@
{
"extends": "./tsconfig.json",
"include": ["src"],
"exclude": ["node_modules"]
}
+38 -38
View File
@@ -5997,14 +5997,14 @@ __metadata:
form-data: 4.0.0
fs-extra: ^10.1.0
handlebars: ^4.7.7
jest: 26.6.3
jest-cli: 26.6.3
jest: ^25.5.4
json-schema-ref-parser: ^9.0.9
node-fetch: 2.6.7
pascalcase: ^2.0.0
qs: 6.10.3
rollup: 3.9.1
rollup-plugin-terser: 7.0.2
ts-jest: ^25.5.1
tslib: 2.3.1
typescript: 4.9.5
languageName: unknown
@@ -24599,29 +24599,6 @@ __metadata:
languageName: node
linkType: hard
"jest-cli@npm:26.6.3, jest-cli@npm:^26.6.3":
version: 26.6.3
resolution: "jest-cli@npm:26.6.3"
dependencies:
"@jest/core": ^26.6.3
"@jest/test-result": ^26.6.2
"@jest/types": ^26.6.2
chalk: ^4.0.0
exit: ^0.1.2
graceful-fs: ^4.2.4
import-local: ^3.0.2
is-ci: ^2.0.0
jest-config: ^26.6.3
jest-util: ^26.6.2
jest-validate: ^26.6.2
prompts: ^2.0.1
yargs: ^15.4.1
bin:
jest: bin/jest.js
checksum: 3f62c26b300549115bcfc0393d7d49467d414d200bb211a8843fd48d0296ddbfc5e6fe808c64ad2039127657b662e3ba3db44166341bd5db2d089bf09cf82a2c
languageName: node
linkType: hard
"jest-cli@npm:^25.5.4":
version: 25.5.4
resolution: "jest-cli@npm:25.5.4"
@@ -24646,6 +24623,29 @@ __metadata:
languageName: node
linkType: hard
"jest-cli@npm:^26.6.3":
version: 26.6.3
resolution: "jest-cli@npm:26.6.3"
dependencies:
"@jest/core": ^26.6.3
"@jest/test-result": ^26.6.2
"@jest/types": ^26.6.2
chalk: ^4.0.0
exit: ^0.1.2
graceful-fs: ^4.2.4
import-local: ^3.0.2
is-ci: ^2.0.0
jest-config: ^26.6.3
jest-util: ^26.6.2
jest-validate: ^26.6.2
prompts: ^2.0.1
yargs: ^15.4.1
bin:
jest: bin/jest.js
checksum: 3f62c26b300549115bcfc0393d7d49467d414d200bb211a8843fd48d0296ddbfc5e6fe808c64ad2039127657b662e3ba3db44166341bd5db2d089bf09cf82a2c
languageName: node
linkType: hard
"jest-cli@npm:^27.5.1":
version: 27.5.1
resolution: "jest-cli@npm:27.5.1"
@@ -26298,19 +26298,6 @@ __metadata:
languageName: node
linkType: hard
"jest@npm:26.6.3, jest@npm:^26.6.3":
version: 26.6.3
resolution: "jest@npm:26.6.3"
dependencies:
"@jest/core": ^26.6.3
import-local: ^3.0.2
jest-cli: ^26.6.3
bin:
jest: bin/jest.js
checksum: 4469f5c426f5b00855e2264dc4fce5ab16c0fab31d2dc6fc829d769ca7ec84a9c74763f7c1d281d085ad55897927a08df2b4778b0df899a66188ff0722e17d29
languageName: node
linkType: hard
"jest@npm:^25.5.2, jest@npm:^25.5.4":
version: 25.5.4
resolution: "jest@npm:25.5.4"
@@ -26324,6 +26311,19 @@ __metadata:
languageName: node
linkType: hard
"jest@npm:^26.6.3":
version: 26.6.3
resolution: "jest@npm:26.6.3"
dependencies:
"@jest/core": ^26.6.3
import-local: ^3.0.2
jest-cli: ^26.6.3
bin:
jest: bin/jest.js
checksum: 4469f5c426f5b00855e2264dc4fce5ab16c0fab31d2dc6fc829d769ca7ec84a9c74763f7c1d281d085ad55897927a08df2b4778b0df899a66188ff0722e17d29
languageName: node
linkType: hard
"jest@npm:^27.0.6, jest@npm:^27.4.7":
version: 27.5.1
resolution: "jest@npm:27.5.1"