Skip to content

Commit

Permalink
Merge pull request #43 from jenskeiner/feature/unit-tests
Browse files Browse the repository at this point in the history
Feature/unit tests
  • Loading branch information
jenskeiner authored Sep 6, 2024
2 parents b4dcda1 + 6964528 commit 978eaa6
Show file tree
Hide file tree
Showing 8 changed files with 334 additions and 46 deletions.
27 changes: 13 additions & 14 deletions citester/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -46529,18 +46529,7 @@ axiosRetry.linearDelay = linearDelay;
axiosRetry.isRetryableError = isRetryableError;
/* harmony default export */ const esm = (axiosRetry);

// EXTERNAL MODULE: external "crypto"
var external_crypto_ = __nccwpck_require__(6113);
;// CONCATENATED MODULE: ./src/utils.ts

/**
* Calculates the digest of a manifest using the SHA256 algorithm.
* @param manifest - The manifest to calculate the digest for.
* @returns The calculated digest in the format "sha256:{digest}".
*/
function calcDigest(manifest) {
return `sha256:${createHash('sha256').update(manifest).digest('hex').toLowerCase()}`;
}
/**
* Parses a challenge string and returns a map of attributes.
* @param challenge - The challenge string to parse.
Expand All @@ -46552,12 +46541,13 @@ function parseChallenge(challenge) {
challenge = challenge.replace('Bearer ', '');
const parts = challenge.split(',');
for (const part of parts) {
const values = part.split('=');
let value = values[1];
const values = part.trim().split('=');
const key = values[0].trim();
let value = values[1].trim();
if (value.startsWith('"') && value.endsWith('"')) {
value = value.substring(1, value.length - 1);
}
attributes.set(values[0], value);
attributes.set(key, value);
}
}
return attributes;
Expand Down Expand Up @@ -46718,13 +46708,19 @@ const Ajv = (jtd_default())["default"] || (jtd_default());
const ajv = new Ajv();
const parseManifest0 = ajv.compileParser(manifestSchema);
function parseManifest(jsonString) {
if (typeof jsonString !== 'string') {
throw new Error('Invalid JSON data');
}
const data = parseManifest0(jsonString);
if (data === undefined) {
core.info(`${parseManifest0.position}`);
core.info(`${parseManifest0.message}`);
core.info(`${jsonString}`);
throw new Error('Invalid JSON data');
}
if (!data.mediaType) {
throw new Error('Unknown media type');
}
switch (data.mediaType) {
case 'application/vnd.oci.image.manifest.v1+json':
return new OCIImageManifestModel(data);
Expand All @@ -46740,6 +46736,9 @@ function parseManifest(jsonString) {
}
const parsePackageVersion0 = ajv.compileParser(packageVersionSchema);
function parsePackageVersion(jsonString) {
if (typeof jsonString !== 'string') {
throw new Error('Invalid JSON data');
}
const data = parsePackageVersion0(jsonString);
if (data === undefined) {
throw new Error('Invalid JSON data');
Expand Down
2 changes: 1 addition & 1 deletion citester/index.js.map

Large diffs are not rendered by default.

27 changes: 13 additions & 14 deletions dist/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -45533,18 +45533,7 @@ axiosRetry.linearDelay = linearDelay;
axiosRetry.isRetryableError = isRetryableError;
/* harmony default export */ const esm = (axiosRetry);

// EXTERNAL MODULE: external "crypto"
var external_crypto_ = __nccwpck_require__(6113);
;// CONCATENATED MODULE: ./src/utils.ts

/**
* Calculates the digest of a manifest using the SHA256 algorithm.
* @param manifest - The manifest to calculate the digest for.
* @returns The calculated digest in the format "sha256:{digest}".
*/
function calcDigest(manifest) {
return `sha256:${createHash('sha256').update(manifest).digest('hex').toLowerCase()}`;
}
/**
* Parses a challenge string and returns a map of attributes.
* @param challenge - The challenge string to parse.
Expand All @@ -45556,12 +45545,13 @@ function parseChallenge(challenge) {
challenge = challenge.replace('Bearer ', '');
const parts = challenge.split(',');
for (const part of parts) {
const values = part.split('=');
let value = values[1];
const values = part.trim().split('=');
const key = values[0].trim();
let value = values[1].trim();
if (value.startsWith('"') && value.endsWith('"')) {
value = value.substring(1, value.length - 1);
}
attributes.set(values[0], value);
attributes.set(key, value);
}
}
return attributes;
Expand Down Expand Up @@ -45722,13 +45712,19 @@ const Ajv = (jtd_default())["default"] || (jtd_default());
const ajv = new Ajv();
const parseManifest0 = ajv.compileParser(manifestSchema);
function parseManifest(jsonString) {
if (typeof jsonString !== 'string') {
throw new Error('Invalid JSON data');
}
const data = parseManifest0(jsonString);
if (data === undefined) {
core.info(`${parseManifest0.position}`);
core.info(`${parseManifest0.message}`);
core.info(`${jsonString}`);
throw new Error('Invalid JSON data');
}
if (!data.mediaType) {
throw new Error('Unknown media type');
}
switch (data.mediaType) {
case 'application/vnd.oci.image.manifest.v1+json':
return new OCIImageManifestModel(data);
Expand All @@ -45744,6 +45740,9 @@ function parseManifest(jsonString) {
}
const parsePackageVersion0 = ajv.compileParser(packageVersionSchema);
function parsePackageVersion(jsonString) {
if (typeof jsonString !== 'string') {
throw new Error('Invalid JSON data');
}
const data = parsePackageVersion0(jsonString);
if (data === undefined) {
throw new Error('Invalid JSON data');
Expand Down
2 changes: 1 addition & 1 deletion dist/index.js.map

Large diffs are not rendered by default.

187 changes: 187 additions & 0 deletions src/parser.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,187 @@
import { parseManifest, parsePackageVersion } from './parser'
import {
OCIImageIndexModel,
OCIImageManifestModel,
DockerImageManifestModel,
DockerManifestListModel,
PackageVersionModel
} from './models'

describe('parseManifest', () => {
test('should parse OCI Image Manifest', () => {
const input = JSON.stringify({
mediaType: 'application/vnd.oci.image.manifest.v1+json',
config: {
mediaType: 'application/vnd.oci.image.config.v1+json',
digest: 'sha256:1234567890abcdef',
size: 1000
},
layers: [
{
mediaType: 'application/vnd.oci.image.layer.v1.tar+gzip',
digest: 'sha256:0987654321fedcba',
size: 2000
}
]
})
const result = parseManifest(input)
expect(result).toBeInstanceOf(OCIImageManifestModel)
expect(result.mediaType).toBe('application/vnd.oci.image.manifest.v1+json')
})

test('should parse OCI Image Index', () => {
const input = JSON.stringify({
mediaType: 'application/vnd.oci.image.index.v1+json',
manifests: [
{
mediaType: 'application/vnd.oci.image.manifest.v1+json',
digest: 'sha256:1234567890abcdef',
size: 1000
}
]
})
const result = parseManifest(input)
expect(result).toBeInstanceOf(OCIImageIndexModel)
expect(result.mediaType).toBe('application/vnd.oci.image.index.v1+json')
})

test('should parse Docker Manifest List', () => {
const input = JSON.stringify({
mediaType: 'application/vnd.docker.distribution.manifest.list.v2+json',
manifests: [
{
mediaType: 'application/vnd.docker.distribution.manifest.v2+json',
digest: 'sha256:1234567890abcdef',
size: 1000
}
]
})
const result = parseManifest(input)
expect(result).toBeInstanceOf(DockerManifestListModel)
expect(result.mediaType).toBe(
'application/vnd.docker.distribution.manifest.list.v2+json'
)
})

test('should parse Docker Image Manifest', () => {
const input = JSON.stringify({
mediaType: 'application/vnd.docker.distribution.manifest.v2+json',
config: {
mediaType: 'application/vnd.docker.container.image.v1+json',
digest: 'sha256:1234567890abcdef',
size: 1000
},
layers: [
{
mediaType: 'application/vnd.docker.image.rootfs.diff.tar.gzip',
digest: 'sha256:0987654321fedcba',
size: 2000
}
]
})
const result = parseManifest(input)
expect(result).toBeInstanceOf(DockerImageManifestModel)
expect(result.mediaType).toBe(
'application/vnd.docker.distribution.manifest.v2+json'
)
})

test('should throw error for invalid JSON', () => {
expect(() => parseManifest('invalid json')).toThrow('Invalid JSON data')
})

test('should throw error for unknown media type', () => {
const input = JSON.stringify({
mediaType: 'application/unknown'
})
expect(() => parseManifest(input)).toThrow('Invalid JSON data')
})

test('should throw error for empty string', () => {
expect(() => parseManifest('')).toThrow('Invalid JSON data')
})

test('should throw error for undefined input', () => {
expect(() => parseManifest(undefined as any)).toThrow('Invalid JSON data')
})

test('should throw error for null input', () => {
expect(() => parseManifest(null as any)).toThrow('Invalid JSON data')
})
})

describe('parsePackageVersion', () => {
test('should parse valid package version', () => {
const input = JSON.stringify({
id: 1,
name: 'package-1.0.0',
url: 'https://example.com/package-1.0.0',
package_html_url: 'https://example.com/package',
created_at: '2023-05-01T12:00:00Z',
updated_at: '2023-05-01T12:00:00Z',
html_url: 'https://example.com/package-1.0.0',
metadata: {
package_type: 'container',
container: {
tags: ['latest', '1.0.0']
}
}
})
const result = parsePackageVersion(input)
expect(result).toBeInstanceOf(PackageVersionModel)
expect(result.id).toBe(1)
expect(result.name).toBe('package-1.0.0')
expect(result.metadata.container.tags).toEqual(['latest', '1.0.0'])
})

test('should parse package version with minimal required fields', () => {
const input = JSON.stringify({
id: 1,
name: 'package-1.0.0',
url: 'https://example.com/package-1.0.0',
package_html_url: 'https://example.com/package',
created_at: '2023-05-01T12:00:00Z',
updated_at: '2023-05-01T12:00:00Z',
html_url: 'https://example.com/package-1.0.0',
metadata: {
package_type: 'container',
container: {
tags: []
}
}
})
const result = parsePackageVersion(input)
expect(result).toBeInstanceOf(PackageVersionModel)
expect(result.id).toBe(1)
expect(result.name).toBe('package-1.0.0')
expect(result.metadata.container.tags).toEqual([])
})

test('should throw error for invalid JSON', () => {
expect(() => parsePackageVersion('invalid json')).toThrow(
'Invalid JSON data'
)
})

test('should throw error for missing required fields', () => {
const input = JSON.stringify({
id: 1,
name: 'package-1.0.0'
})
expect(() => parsePackageVersion(input)).toThrow('Invalid JSON data')
})

test('should throw error for empty string', () => {
expect(() => parsePackageVersion('')).toThrow('Invalid JSON data')
})

test('should throw error for undefined input', () => {
expect(() => parsePackageVersion(undefined as any)).toThrow(
'Invalid JSON data'
)
})

test('should throw error for null input', () => {
expect(() => parsePackageVersion(null as any)).toThrow('Invalid JSON data')
})
})
16 changes: 14 additions & 2 deletions src/parser.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as core from '@actions/core'
import AjvModule from 'ajv/dist/jtd.js'
import { manifestSchema, packageVersionSchema } from './schemas.js'
import { manifestSchema, packageVersionSchema } from './schemas'
import {
Manifest,
OCIImageIndexModel,
Expand All @@ -10,7 +10,7 @@ import {
PackageVersionModel,
PackageVersionExt,
PackageVersion
} from './models.js'
} from './models'

const Ajv = (AjvModule as any).default || AjvModule
const ajv = new Ajv()
Expand All @@ -24,6 +24,10 @@ export function parseManifest(
| OCIImageManifestModel
| DockerImageManifestModel
| DockerManifestListModel {
if (typeof jsonString !== 'string') {
throw new Error('Invalid JSON data')
}

const data = parseManifest0(jsonString) as Manifest

if (data === undefined) {
Expand All @@ -33,6 +37,10 @@ export function parseManifest(
throw new Error('Invalid JSON data')
}

if (!data.mediaType) {
throw new Error('Unknown media type')
}

switch (data.mediaType) {
case 'application/vnd.oci.image.manifest.v1+json':
return new OCIImageManifestModel(data)
Expand All @@ -50,6 +58,10 @@ export function parseManifest(
const parsePackageVersion0 = ajv.compileParser(packageVersionSchema)

export function parsePackageVersion(jsonString: string): PackageVersionExt {
if (typeof jsonString !== 'string') {
throw new Error('Invalid JSON data')
}

const data = parsePackageVersion0(jsonString) as PackageVersion

if (data === undefined) {
Expand Down
Loading

0 comments on commit 978eaa6

Please sign in to comment.