Files
smartregistry/test/test.npm.ts
2025-11-19 20:45:37 +00:00

362 lines
10 KiB
TypeScript

import { expect, tap } from '@git.zone/tstest/tapbundle';
import { SmartRegistry } from '../ts/index.js';
import { createTestRegistry, createTestTokens, createTestPackument } from './helpers/registry.js';
let registry: SmartRegistry;
let npmToken: string;
let userId: string;
// Test data
const testPackageName = 'test-package';
const testVersion = '1.0.0';
const testTarballData = Buffer.from('fake tarball content', 'utf-8');
tap.test('NPM: should create registry instance', async () => {
registry = await createTestRegistry();
const tokens = await createTestTokens(registry);
npmToken = tokens.npmToken;
userId = tokens.userId;
expect(registry).toBeInstanceOf(SmartRegistry);
expect(npmToken).toBeTypeOf('string');
});
tap.test('NPM: should handle user authentication (PUT /-/user/org.couchdb.user:{user})', async () => {
const response = await registry.handleRequest({
method: 'PUT',
path: '/npm/-/user/org.couchdb.user:testuser',
headers: {},
query: {},
body: {
name: 'testuser',
password: 'testpass',
},
});
expect(response.status).toEqual(201);
expect(response.body).toHaveProperty('token');
expect((response.body as any).token).toBeTypeOf('string');
});
tap.test('NPM: should publish a package (PUT /{package})', async () => {
const packument = createTestPackument(testPackageName, testVersion, testTarballData);
const response = await registry.handleRequest({
method: 'PUT',
path: `/npm/${testPackageName}`,
headers: {
Authorization: `Bearer ${npmToken}`,
'Content-Type': 'application/json',
},
query: {},
body: packument,
});
expect(response.status).toEqual(201);
expect(response.body).toHaveProperty('ok');
expect((response.body as any).ok).toEqual(true);
});
tap.test('NPM: should retrieve package metadata (GET /{package})', async () => {
const response = await registry.handleRequest({
method: 'GET',
path: `/npm/${testPackageName}`,
headers: {},
query: {},
});
expect(response.status).toEqual(200);
expect(response.body).toHaveProperty('name');
expect((response.body as any).name).toEqual(testPackageName);
expect((response.body as any).versions).toHaveProperty(testVersion);
expect((response.body as any)['dist-tags'].latest).toEqual(testVersion);
});
tap.test('NPM: should retrieve specific version metadata (GET /{package}/{version})', async () => {
const response = await registry.handleRequest({
method: 'GET',
path: `/npm/${testPackageName}/${testVersion}`,
headers: {},
query: {},
});
expect(response.status).toEqual(200);
expect(response.body).toHaveProperty('version');
expect((response.body as any).version).toEqual(testVersion);
expect((response.body as any).name).toEqual(testPackageName);
});
tap.test('NPM: should download tarball (GET /{package}/-/{tarball})', async () => {
const response = await registry.handleRequest({
method: 'GET',
path: `/npm/${testPackageName}/-/${testPackageName}-${testVersion}.tgz`,
headers: {},
query: {},
});
expect(response.status).toEqual(200);
expect(response.body).toBeInstanceOf(Buffer);
expect((response.body as Buffer).toString('utf-8')).toEqual('fake tarball content');
expect(response.headers['Content-Type']).toEqual('application/octet-stream');
});
tap.test('NPM: should publish a new version of the package', async () => {
const newVersion = '1.1.0';
const newTarballData = Buffer.from('new version tarball', 'utf-8');
const packument = createTestPackument(testPackageName, newVersion, newTarballData);
const response = await registry.handleRequest({
method: 'PUT',
path: `/npm/${testPackageName}`,
headers: {
Authorization: `Bearer ${npmToken}`,
'Content-Type': 'application/json',
},
query: {},
body: packument,
});
expect(response.status).toEqual(201);
// Verify the new version is available
const getResponse = await registry.handleRequest({
method: 'GET',
path: `/npm/${testPackageName}`,
headers: {},
query: {},
});
expect(getResponse.status).toEqual(200);
expect((getResponse.body as any).versions).toHaveProperty(newVersion);
});
tap.test('NPM: should get dist-tags (GET /-/package/{pkg}/dist-tags)', async () => {
const response = await registry.handleRequest({
method: 'GET',
path: `/npm/-/package/${testPackageName}/dist-tags`,
headers: {},
query: {},
});
expect(response.status).toEqual(200);
expect(response.body).toHaveProperty('latest');
expect((response.body as any).latest).toBeTypeOf('string');
});
tap.test('NPM: should update dist-tag (PUT /-/package/{pkg}/dist-tags/{tag})', async () => {
const response = await registry.handleRequest({
method: 'PUT',
path: `/npm/-/package/${testPackageName}/dist-tags/beta`,
headers: {
Authorization: `Bearer ${npmToken}`,
'Content-Type': 'application/json',
},
query: {},
body: '1.1.0',
});
expect(response.status).toEqual(200);
// Verify the tag was updated
const getResponse = await registry.handleRequest({
method: 'GET',
path: `/npm/${testPackageName}`,
headers: {},
query: {},
});
expect((getResponse.body as any)['dist-tags'].beta).toEqual('1.1.0');
});
tap.test('NPM: should delete dist-tag (DELETE /-/package/{pkg}/dist-tags/{tag})', async () => {
const response = await registry.handleRequest({
method: 'DELETE',
path: `/npm/-/package/${testPackageName}/dist-tags/beta`,
headers: {
Authorization: `Bearer ${npmToken}`,
},
query: {},
});
expect(response.status).toEqual(200);
// Verify the tag was deleted
const getResponse = await registry.handleRequest({
method: 'GET',
path: `/npm/${testPackageName}`,
headers: {},
query: {},
});
expect((getResponse.body as any)['dist-tags']).not.toHaveProperty('beta');
});
tap.test('NPM: should create a new token (POST /-/npm/v1/tokens)', async () => {
const response = await registry.handleRequest({
method: 'POST',
path: '/npm/-/npm/v1/tokens',
headers: {
Authorization: `Bearer ${npmToken}`,
'Content-Type': 'application/json',
},
query: {},
body: {
password: 'testpass',
readonly: true,
cidr_whitelist: [],
},
});
expect(response.status).toEqual(200);
expect(response.body).toHaveProperty('token');
expect((response.body as any).readonly).toEqual(true);
});
tap.test('NPM: should list tokens (GET /-/npm/v1/tokens)', async () => {
const response = await registry.handleRequest({
method: 'GET',
path: '/npm/-/npm/v1/tokens',
headers: {
Authorization: `Bearer ${npmToken}`,
},
query: {},
});
expect(response.status).toEqual(200);
expect(response.body).toHaveProperty('objects');
expect((response.body as any).objects).toBeInstanceOf(Array);
expect((response.body as any).objects.length).toBeGreaterThan(0);
});
tap.test('NPM: should search packages (GET /-/v1/search)', async () => {
const response = await registry.handleRequest({
method: 'GET',
path: '/npm/-/v1/search',
headers: {},
query: {
text: 'test',
size: '20',
},
});
expect(response.status).toEqual(200);
expect(response.body).toHaveProperty('objects');
expect((response.body as any).objects).toBeInstanceOf(Array);
expect((response.body as any).total).toBeGreaterThan(0);
});
tap.test('NPM: should search packages with specific query', async () => {
const response = await registry.handleRequest({
method: 'GET',
path: '/npm/-/v1/search',
headers: {},
query: {
text: testPackageName,
},
});
expect(response.status).toEqual(200);
const results = (response.body as any).objects;
expect(results.length).toBeGreaterThan(0);
expect(results[0].package.name).toEqual(testPackageName);
});
tap.test('NPM: should unpublish a specific version (DELETE /{package}/-/{version})', async () => {
const response = await registry.handleRequest({
method: 'DELETE',
path: `/npm/${testPackageName}/-/${testVersion}`,
headers: {
Authorization: `Bearer ${npmToken}`,
},
query: {},
});
expect(response.status).toEqual(200);
// Verify the version was removed
const getResponse = await registry.handleRequest({
method: 'GET',
path: `/npm/${testPackageName}`,
headers: {},
query: {},
});
expect((getResponse.body as any).versions).not.toHaveProperty(testVersion);
});
tap.test('NPM: should unpublish entire package (DELETE /{package}/-rev/{rev})', async () => {
const response = await registry.handleRequest({
method: 'DELETE',
path: `/npm/${testPackageName}/-rev/1`,
headers: {
Authorization: `Bearer ${npmToken}`,
},
query: {},
});
expect(response.status).toEqual(200);
// Verify the package was removed
const getResponse = await registry.handleRequest({
method: 'GET',
path: `/npm/${testPackageName}`,
headers: {},
query: {},
});
expect(getResponse.status).toEqual(404);
});
tap.test('NPM: should return 404 for non-existent package', async () => {
const response = await registry.handleRequest({
method: 'GET',
path: '/npm/non-existent-package',
headers: {},
query: {},
});
expect(response.status).toEqual(404);
expect(response.body).toHaveProperty('error');
});
tap.test('NPM: should return 401 for unauthorized publish', async () => {
const packument = createTestPackument('unauthorized-package', '1.0.0', testTarballData);
const response = await registry.handleRequest({
method: 'PUT',
path: '/npm/unauthorized-package',
headers: {
// No authorization header
'Content-Type': 'application/json',
},
query: {},
body: packument,
});
expect(response.status).toEqual(401);
expect(response.body).toHaveProperty('error');
});
tap.test('NPM: should reject readonly token for write operations', async () => {
// Create a readonly token
const authManager = registry.getAuthManager();
const readonlyToken = await authManager.createNpmToken(userId, true);
const packument = createTestPackument('readonly-test', '1.0.0', testTarballData);
const response = await registry.handleRequest({
method: 'PUT',
path: '/npm/readonly-test',
headers: {
Authorization: `Bearer ${readonlyToken}`,
'Content-Type': 'application/json',
},
query: {},
body: packument,
});
expect(response.status).toEqual(401);
});
export default tap.start();