Files
smartregistry/test/test.maven.ts

373 lines
12 KiB
TypeScript

import { expect, tap } from '@git.zone/tstest/tapbundle';
import { SmartRegistry } from '../ts/index.js';
import {
createTestRegistry,
createTestTokens,
createTestPom,
createTestJar,
calculateMavenChecksums,
} from './helpers/registry.js';
let registry: SmartRegistry;
let mavenToken: string;
let userId: string;
// Test data
const testGroupId = 'com.example.test';
const testArtifactId = 'test-artifact';
const testVersion = '1.0.0';
const testJarData = createTestJar();
const testPomData = Buffer.from(
createTestPom(testGroupId, testArtifactId, testVersion),
'utf-8'
);
tap.test('Maven: should create registry instance', async () => {
registry = await createTestRegistry();
const tokens = await createTestTokens(registry);
mavenToken = tokens.mavenToken;
userId = tokens.userId;
expect(registry).toBeInstanceOf(SmartRegistry);
expect(mavenToken).toBeTypeOf('string');
});
tap.test('Maven: should upload POM file (PUT /{groupPath}/{artifactId}/{version}/*.pom)', async () => {
const groupPath = testGroupId.replace(/\./g, '/');
const pomFilename = `${testArtifactId}-${testVersion}.pom`;
const response = await registry.handleRequest({
method: 'PUT',
path: `/maven/${groupPath}/${testArtifactId}/${testVersion}/${pomFilename}`,
headers: {
Authorization: `Bearer ${mavenToken}`,
'Content-Type': 'application/xml',
},
query: {},
body: testPomData,
});
expect(response.status).toEqual(201);
});
tap.test('Maven: should upload JAR file (PUT /{groupPath}/{artifactId}/{version}/*.jar)', async () => {
const groupPath = testGroupId.replace(/\./g, '/');
const jarFilename = `${testArtifactId}-${testVersion}.jar`;
const response = await registry.handleRequest({
method: 'PUT',
path: `/maven/${groupPath}/${testArtifactId}/${testVersion}/${jarFilename}`,
headers: {
Authorization: `Bearer ${mavenToken}`,
'Content-Type': 'application/java-archive',
},
query: {},
body: testJarData,
});
expect(response.status).toEqual(201);
});
tap.test('Maven: should retrieve uploaded POM file (GET)', async () => {
const groupPath = testGroupId.replace(/\./g, '/');
const pomFilename = `${testArtifactId}-${testVersion}.pom`;
const response = await registry.handleRequest({
method: 'GET',
path: `/maven/${groupPath}/${testArtifactId}/${testVersion}/${pomFilename}`,
headers: {},
query: {},
});
expect(response.status).toEqual(200);
expect(response.body).toBeInstanceOf(Buffer);
expect((response.body as Buffer).toString('utf-8')).toContain(testGroupId);
expect((response.body as Buffer).toString('utf-8')).toContain(testArtifactId);
expect((response.body as Buffer).toString('utf-8')).toContain(testVersion);
expect(response.headers['Content-Type']).toEqual('application/xml');
});
tap.test('Maven: should retrieve uploaded JAR file (GET)', async () => {
const groupPath = testGroupId.replace(/\./g, '/');
const jarFilename = `${testArtifactId}-${testVersion}.jar`;
const response = await registry.handleRequest({
method: 'GET',
path: `/maven/${groupPath}/${testArtifactId}/${testVersion}/${jarFilename}`,
headers: {},
query: {},
});
expect(response.status).toEqual(200);
expect(response.body).toBeInstanceOf(Buffer);
expect(response.headers['Content-Type']).toEqual('application/java-archive');
});
tap.test('Maven: should retrieve MD5 checksum for JAR (GET *.jar.md5)', async () => {
const groupPath = testGroupId.replace(/\./g, '/');
const jarFilename = `${testArtifactId}-${testVersion}.jar`;
const checksums = calculateMavenChecksums(testJarData);
const response = await registry.handleRequest({
method: 'GET',
path: `/maven/${groupPath}/${testArtifactId}/${testVersion}/${jarFilename}.md5`,
headers: {},
query: {},
});
expect(response.status).toEqual(200);
expect(response.body).toBeInstanceOf(Buffer);
expect((response.body as Buffer).toString('utf-8')).toEqual(checksums.md5);
expect(response.headers['Content-Type']).toEqual('text/plain');
});
tap.test('Maven: should retrieve SHA1 checksum for JAR (GET *.jar.sha1)', async () => {
const groupPath = testGroupId.replace(/\./g, '/');
const jarFilename = `${testArtifactId}-${testVersion}.jar`;
const checksums = calculateMavenChecksums(testJarData);
const response = await registry.handleRequest({
method: 'GET',
path: `/maven/${groupPath}/${testArtifactId}/${testVersion}/${jarFilename}.sha1`,
headers: {},
query: {},
});
expect(response.status).toEqual(200);
expect(response.body).toBeInstanceOf(Buffer);
expect((response.body as Buffer).toString('utf-8')).toEqual(checksums.sha1);
expect(response.headers['Content-Type']).toEqual('text/plain');
});
tap.test('Maven: should retrieve SHA256 checksum for JAR (GET *.jar.sha256)', async () => {
const groupPath = testGroupId.replace(/\./g, '/');
const jarFilename = `${testArtifactId}-${testVersion}.jar`;
const checksums = calculateMavenChecksums(testJarData);
const response = await registry.handleRequest({
method: 'GET',
path: `/maven/${groupPath}/${testArtifactId}/${testVersion}/${jarFilename}.sha256`,
headers: {},
query: {},
});
expect(response.status).toEqual(200);
expect(response.body).toBeInstanceOf(Buffer);
expect((response.body as Buffer).toString('utf-8')).toEqual(checksums.sha256);
expect(response.headers['Content-Type']).toEqual('text/plain');
});
tap.test('Maven: should retrieve SHA512 checksum for JAR (GET *.jar.sha512)', async () => {
const groupPath = testGroupId.replace(/\./g, '/');
const jarFilename = `${testArtifactId}-${testVersion}.jar`;
const checksums = calculateMavenChecksums(testJarData);
const response = await registry.handleRequest({
method: 'GET',
path: `/maven/${groupPath}/${testArtifactId}/${testVersion}/${jarFilename}.sha512`,
headers: {},
query: {},
});
expect(response.status).toEqual(200);
expect(response.body).toBeInstanceOf(Buffer);
expect((response.body as Buffer).toString('utf-8')).toEqual(checksums.sha512);
expect(response.headers['Content-Type']).toEqual('text/plain');
});
tap.test('Maven: should retrieve maven-metadata.xml (GET)', async () => {
const groupPath = testGroupId.replace(/\./g, '/');
const response = await registry.handleRequest({
method: 'GET',
path: `/maven/${groupPath}/${testArtifactId}/maven-metadata.xml`,
headers: {},
query: {},
});
expect(response.status).toEqual(200);
expect(response.body).toBeInstanceOf(Buffer);
const xml = (response.body as Buffer).toString('utf-8');
expect(xml).toContain('<groupId>');
expect(xml).toContain('<artifactId>');
expect(xml).toContain('<version>1.0.0</version>');
expect(xml).toContain('<latest>1.0.0</latest>');
expect(xml).toContain('<release>1.0.0</release>');
expect(response.headers['Content-Type']).toEqual('application/xml');
});
tap.test('Maven: should upload a second version and update metadata', async () => {
const groupPath = testGroupId.replace(/\./g, '/');
const newVersion = '2.0.0';
const pomFilename = `${testArtifactId}-${newVersion}.pom`;
const jarFilename = `${testArtifactId}-${newVersion}.jar`;
const newPomData = Buffer.from(
createTestPom(testGroupId, testArtifactId, newVersion),
'utf-8'
);
// Upload POM
await registry.handleRequest({
method: 'PUT',
path: `/maven/${groupPath}/${testArtifactId}/${newVersion}/${pomFilename}`,
headers: {
Authorization: `Bearer ${mavenToken}`,
'Content-Type': 'application/xml',
},
query: {},
body: newPomData,
});
// Upload JAR
await registry.handleRequest({
method: 'PUT',
path: `/maven/${groupPath}/${testArtifactId}/${newVersion}/${jarFilename}`,
headers: {
Authorization: `Bearer ${mavenToken}`,
'Content-Type': 'application/java-archive',
},
query: {},
body: testJarData,
});
// Retrieve metadata and verify both versions are present
const response = await registry.handleRequest({
method: 'GET',
path: `/maven/${groupPath}/${testArtifactId}/maven-metadata.xml`,
headers: {},
query: {},
});
expect(response.status).toEqual(200);
const xml = (response.body as Buffer).toString('utf-8');
expect(xml).toContain('<version>1.0.0</version>');
expect(xml).toContain('<version>2.0.0</version>');
expect(xml).toContain('<latest>2.0.0</latest>');
expect(xml).toContain('<release>2.0.0</release>');
});
tap.test('Maven: should upload WAR file with correct content type', async () => {
const groupPath = testGroupId.replace(/\./g, '/');
const warVersion = '1.0.0-war';
const warFilename = `${testArtifactId}-${warVersion}.war`;
const warData = Buffer.from('fake war content', 'utf-8');
const response = await registry.handleRequest({
method: 'PUT',
path: `/maven/${groupPath}/${testArtifactId}/${warVersion}/${warFilename}`,
headers: {
Authorization: `Bearer ${mavenToken}`,
'Content-Type': 'application/x-webarchive',
},
query: {},
body: warData,
});
expect(response.status).toEqual(201);
});
tap.test('Maven: should return 404 for non-existent artifact', async () => {
const groupPath = 'com/example/nonexistent';
const response = await registry.handleRequest({
method: 'GET',
path: `/maven/${groupPath}/fake-artifact/1.0.0/fake-artifact-1.0.0.jar`,
headers: {},
query: {},
});
expect(response.status).toEqual(404);
expect(response.body).toHaveProperty('error');
});
tap.test('Maven: should return 401 for unauthorized upload', async () => {
const groupPath = testGroupId.replace(/\./g, '/');
const jarFilename = `${testArtifactId}-3.0.0.jar`;
const response = await registry.handleRequest({
method: 'PUT',
path: `/maven/${groupPath}/${testArtifactId}/3.0.0/${jarFilename}`,
headers: {
// No authorization header
'Content-Type': 'application/java-archive',
},
query: {},
body: testJarData,
});
expect(response.status).toEqual(401);
expect(response.body).toHaveProperty('error');
});
tap.test('Maven: should reject POM upload with mismatched GAV', async () => {
const groupPath = 'com/mismatch/test';
const pomFilename = `different-artifact-1.0.0.pom`;
// POM contains different GAV than the path
const mismatchedPom = Buffer.from(
createTestPom('com.other.group', 'other-artifact', '1.0.0'),
'utf-8'
);
const response = await registry.handleRequest({
method: 'PUT',
path: `/maven/${groupPath}/different-artifact/1.0.0/${pomFilename}`,
headers: {
Authorization: `Bearer ${mavenToken}`,
'Content-Type': 'application/xml',
},
query: {},
body: mismatchedPom,
});
expect(response.status).toEqual(400);
expect(response.body).toHaveProperty('error');
});
tap.test('Maven: should delete an artifact (DELETE)', async () => {
const groupPath = testGroupId.replace(/\./g, '/');
const jarFilename = `${testArtifactId}-${testVersion}.jar`;
const response = await registry.handleRequest({
method: 'DELETE',
path: `/maven/${groupPath}/${testArtifactId}/${testVersion}/${jarFilename}`,
headers: {
Authorization: `Bearer ${mavenToken}`,
},
query: {},
});
expect(response.status).toEqual(200);
// Verify artifact was deleted
const getResponse = await registry.handleRequest({
method: 'GET',
path: `/maven/${groupPath}/${testArtifactId}/${testVersion}/${jarFilename}`,
headers: {},
query: {},
});
expect(getResponse.status).toEqual(404);
});
tap.test('Maven: should return 404 for checksum of deleted artifact', async () => {
const groupPath = testGroupId.replace(/\./g, '/');
const jarFilename = `${testArtifactId}-${testVersion}.jar`;
const response = await registry.handleRequest({
method: 'GET',
path: `/maven/${groupPath}/${testArtifactId}/${testVersion}/${jarFilename}.md5`,
headers: {},
query: {},
});
expect(response.status).toEqual(404);
});
tap.postTask('cleanup registry', async () => {
if (registry) {
registry.destroy();
}
});
export default tap.start();