From 554198cb28a5b2512b39d099c03ffa399536196f Mon Sep 17 00:00:00 2001 From: Sebastian Beltran Date: Tue, 4 Mar 2025 10:53:27 -0500 Subject: [PATCH 1/3] feat: enhance Project constructor to support various input formats and add validation --- lib/project.js | 24 +++++++++++++-- test/project.test.js | 72 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 93 insertions(+), 3 deletions(-) create mode 100644 test/project.test.js diff --git a/lib/project.js b/lib/project.js index 7b0bacf..457d3ec 100644 --- a/lib/project.js +++ b/lib/project.js @@ -1,20 +1,38 @@ 'use strict' module.exports.Project = class Project { + /** + * Constructs a new Project instance. + * + * @param {object|string} proj - The project information. It can be a string in the format "repoOwner/repoName" or an object with the following properties: + * @param {string} [proj.repo] - The repository in the format "repoOwner/repoName". + * @param {string} [proj.repoOwner] - The owner of the repository. + * @param {string} [proj.repoName] - The name of the repository. + * @param {string} [proj.name] - The name of the project. + * @param {string} [proj.repoBranch] - The branch of the repository. + * @param {string} [proj.repoDirectory] - The directory of the repository. + */ constructor (proj) { let repo let repoOwner let repoName if (typeof proj === 'string') { [repoOwner, repoName] = proj.split('/') + + if (!repoOwner || !repoName) { + throw new Error('Invalid repo format. It should be in the format "repoOwner/repoName".') + } + repo = proj - } else if (proj.repo && (!proj.repoOwner || !proj.repoName)) { + } else if (proj?.repo) { [repoOwner, repoName] = proj.repo.split('/') repo = proj.repo repoOwner = proj.repoOwner || repoOwner repoName = proj.repoName || repoName - } else if (!proj.repo && proj.repoOwner && proj.repoName) { - repo = `${proj.repoOwner}/${proj.repoName}` + } else { + if (proj?.repoOwner && proj?.repoName) { + repo = `${proj.repoOwner}/${proj.repoName}` + } repoOwner = proj.repoOwner repoName = proj.repoName } diff --git a/test/project.test.js b/test/project.test.js new file mode 100644 index 0000000..0113932 --- /dev/null +++ b/test/project.test.js @@ -0,0 +1,72 @@ +const assert = require('assert') +const { it, describe } = require('mocha') +const { Project } = require('../lib/project') + +describe('Project', () => { + it('should initialize with a string repo', () => { + const proj = new Project('owner/repo') + assert.strictEqual(proj.repo, 'owner/repo') + assert.strictEqual(proj.repoOwner, 'owner') + assert.strictEqual(proj.repoName, 'repo') + assert.strictEqual(proj.name, 'owner/repo') + assert.strictEqual(proj.repoBranch, undefined) + assert.strictEqual(proj.repoDirectory, '/') + assert.strictEqual(proj.packageName, null) + }) + + it('should throw an error if the repo format is invalid', () => { + assert.throws(() => new Project('owner'), { + name: 'Error', + message: 'Invalid repo format. It should be in the format "repoOwner/repoName".' + }) + }) + + it('should initialize with an object containing repo', () => { + const proj = new Project({ repo: 'owner/repo' }) + assert.strictEqual(proj.repo, 'owner/repo') + assert.strictEqual(proj.repoOwner, 'owner') + assert.strictEqual(proj.repoName, 'repo') + assert.strictEqual(proj.name, 'owner/repo') + assert.strictEqual(proj.repoBranch, undefined) + assert.strictEqual(proj.repoDirectory, '/') + assert.strictEqual(proj.packageName, null) + }) + + it('should initialize with an object containing repoOwner and repoName', () => { + const proj = new Project({ repoOwner: 'owner', repoName: 'repo' }) + assert.strictEqual(proj.repo, 'owner/repo') + assert.strictEqual(proj.repoOwner, 'owner') + assert.strictEqual(proj.repoName, 'repo') + assert.strictEqual(proj.name, 'owner/repo') + assert.strictEqual(proj.repoBranch, undefined) + assert.strictEqual(proj.repoDirectory, '/') + assert.strictEqual(proj.packageName, null) + }) + + it('should initialize with an object containing only repoName', () => { + const proj = new Project({ repoName: 'repo' }) + assert.strictEqual(proj.repo, undefined) + assert.strictEqual(proj.repoOwner, undefined) + assert.strictEqual(proj.repoName, 'repo') + assert.strictEqual(proj.name, undefined) + assert.strictEqual(proj.repoBranch, undefined) + assert.strictEqual(proj.repoDirectory, '/') + assert.strictEqual(proj.packageName, null) + }) + + it('should initialize with an object containing all properties', () => { + const proj = new Project({ + name: 'customName', + repo: 'owner/repo', + repoBranch: 'main', + repoDirectory: '/src' + }) + assert.strictEqual(proj.repo, 'owner/repo') + assert.strictEqual(proj.repoOwner, 'owner') + assert.strictEqual(proj.repoName, 'repo') + assert.strictEqual(proj.name, 'customName') + assert.strictEqual(proj.repoBranch, 'main') + assert.strictEqual(proj.repoDirectory, '/src') + assert.strictEqual(proj.packageName, null) + }) +}) From 1dff2e25e8c73860a999b66388e4974e6c086272 Mon Sep 17 00:00:00 2001 From: Sebastian Beltran Date: Tue, 4 Mar 2025 10:57:07 -0500 Subject: [PATCH 2/3] test: add unit tests for Organization and Project classes --- test/{project.test.js => models.test.js} | 43 ++++++++++++++++++++++-- 1 file changed, 41 insertions(+), 2 deletions(-) rename test/{project.test.js => models.test.js} (62%) diff --git a/test/project.test.js b/test/models.test.js similarity index 62% rename from test/project.test.js rename to test/models.test.js index 0113932..37ea6e6 100644 --- a/test/project.test.js +++ b/test/models.test.js @@ -1,6 +1,45 @@ -const assert = require('assert') -const { it, describe } = require('mocha') +const assert = require('assert'); +const { Organization } = require('../lib/organization'); const { Project } = require('../lib/project') +const { describe, it } = require('mocha'); + +describe('Organization', function() { + it('should create an organization with a name string', function() { + const org = new Organization('TestOrg'); + assert.strictEqual(org.name, 'TestOrg'); + assert.strictEqual(org.displayName, 'TestOrg'); + assert.strictEqual(org.url, undefined); + }); + + it('should create an organization with an object', function() { + const org = new Organization({ name: 'TestOrg', displayName: 'Test Organization', url: 'http://test.org' }); + assert.strictEqual(org.name, 'TestOrg'); + assert.strictEqual(org.displayName, 'Test Organization'); + assert.strictEqual(org.url, 'http://test.org'); + }); + + it('should use name as displayName if displayName is not provided', function() { + const org = new Organization({ name: 'TestOrg' }); + assert.strictEqual(org.name, 'TestOrg'); + assert.strictEqual(org.displayName, 'TestOrg'); + assert.strictEqual(org.url, undefined); + }); + + it('should handle empty object input', function() { + const org = new Organization({}); + assert.strictEqual(org.name, undefined); + assert.strictEqual(org.displayName, undefined); + assert.strictEqual(org.url, undefined); + }); + + it('should handle no input', function() { + const org = new Organization(); + assert.strictEqual(org.name, undefined); + assert.strictEqual(org.displayName, undefined); + assert.strictEqual(org.url, undefined); + }); +}); + describe('Project', () => { it('should initialize with a string repo', () => { From 08ad8745df4cf66fbf95c77086ba625433144775 Mon Sep 17 00:00:00 2001 From: Sebastian Beltran Date: Tue, 4 Mar 2025 11:05:13 -0500 Subject: [PATCH 3/3] test: add unit tests for Manifest and Packument classes --- test/models.test.js | 155 ++++++++++++++++++++++++++++++++------------ 1 file changed, 115 insertions(+), 40 deletions(-) diff --git a/test/models.test.js b/test/models.test.js index 37ea6e6..9e028c8 100644 --- a/test/models.test.js +++ b/test/models.test.js @@ -1,45 +1,45 @@ -const assert = require('assert'); -const { Organization } = require('../lib/organization'); +const assert = require('assert') +const { Organization } = require('../lib/organization') const { Project } = require('../lib/project') -const { describe, it } = require('mocha'); - -describe('Organization', function() { - it('should create an organization with a name string', function() { - const org = new Organization('TestOrg'); - assert.strictEqual(org.name, 'TestOrg'); - assert.strictEqual(org.displayName, 'TestOrg'); - assert.strictEqual(org.url, undefined); - }); - - it('should create an organization with an object', function() { - const org = new Organization({ name: 'TestOrg', displayName: 'Test Organization', url: 'http://test.org' }); - assert.strictEqual(org.name, 'TestOrg'); - assert.strictEqual(org.displayName, 'Test Organization'); - assert.strictEqual(org.url, 'http://test.org'); - }); - - it('should use name as displayName if displayName is not provided', function() { - const org = new Organization({ name: 'TestOrg' }); - assert.strictEqual(org.name, 'TestOrg'); - assert.strictEqual(org.displayName, 'TestOrg'); - assert.strictEqual(org.url, undefined); - }); - - it('should handle empty object input', function() { - const org = new Organization({}); - assert.strictEqual(org.name, undefined); - assert.strictEqual(org.displayName, undefined); - assert.strictEqual(org.url, undefined); - }); - - it('should handle no input', function() { - const org = new Organization(); - assert.strictEqual(org.name, undefined); - assert.strictEqual(org.displayName, undefined); - assert.strictEqual(org.url, undefined); - }); -}); +const { Manifest, Packument } = require('../lib/npm') +const { describe, it } = require('mocha') +describe('Organization', function () { + it('should create an organization with a name string', function () { + const org = new Organization('TestOrg') + assert.strictEqual(org.name, 'TestOrg') + assert.strictEqual(org.displayName, 'TestOrg') + assert.strictEqual(org.url, undefined) + }) + + it('should create an organization with an object', function () { + const org = new Organization({ name: 'TestOrg', displayName: 'Test Organization', url: 'http://test.org' }) + assert.strictEqual(org.name, 'TestOrg') + assert.strictEqual(org.displayName, 'Test Organization') + assert.strictEqual(org.url, 'http://test.org') + }) + + it('should use name as displayName if displayName is not provided', function () { + const org = new Organization({ name: 'TestOrg' }) + assert.strictEqual(org.name, 'TestOrg') + assert.strictEqual(org.displayName, 'TestOrg') + assert.strictEqual(org.url, undefined) + }) + + it('should handle empty object input', function () { + const org = new Organization({}) + assert.strictEqual(org.name, undefined) + assert.strictEqual(org.displayName, undefined) + assert.strictEqual(org.url, undefined) + }) + + it('should handle no input', function () { + const org = new Organization() + assert.strictEqual(org.name, undefined) + assert.strictEqual(org.displayName, undefined) + assert.strictEqual(org.url, undefined) + }) +}) describe('Project', () => { it('should initialize with a string repo', () => { @@ -109,3 +109,78 @@ describe('Project', () => { assert.strictEqual(proj.packageName, null) }) }) + +describe('Manifest', function () { + it('should correctly initialize with given manifest data', function () { + const manifestData = { + name: 'test-package', + version: '1.0.0', + dependencies: { dep1: '^1.0.0' }, + optionalDependencies: { optDep1: '^1.0.0' }, + devDependencies: { devDep1: '^1.0.0' }, + peerDependencies: { peerDep1: '^1.0.0' }, + bundleDependencies: { bundleDep1: '^1.0.0' }, + bin: { bin1: 'bin1.js' } + } + + const manifest = new Manifest(manifestData) + + assert.strictEqual(manifest.name, manifestData.name) + assert.strictEqual(manifest.version, manifestData.version) + assert.deepStrictEqual(manifest.dependencies, manifestData.dependencies) + assert.deepStrictEqual(manifest.optionalDependencies, manifestData.optionalDependencies) + assert.deepStrictEqual(manifest.devDependencies, manifestData.devDependencies) + assert.deepStrictEqual(manifest.peerDependencies, manifestData.peerDependencies) + assert.deepStrictEqual(manifest.bundleDependencies, manifestData.bundleDependencies) + assert.deepStrictEqual(manifest.bin, manifestData.bin) + }) + + it('should handle missing optional fields', function () { + const manifestData = { + name: 'test-package', + version: '1.0.0' + } + + const manifest = new Manifest(manifestData) + + assert.strictEqual(manifest.name, manifestData.name) + assert.strictEqual(manifest.version, manifestData.version) + assert.strictEqual(manifest.dependencies, undefined) + assert.strictEqual(manifest.optionalDependencies, undefined) + assert.strictEqual(manifest.devDependencies, undefined) + assert.strictEqual(manifest.peerDependencies, undefined) + assert.strictEqual(manifest.bundleDependencies, undefined) + assert.strictEqual(manifest.bin, undefined) + }) +}) + +describe('Packument', function () { + it('should create an instance with the correct properties', function () { + const packumentData = { + name: 'example-package', + distTags: { latest: '1.0.0' }, + modified: '2023-10-01T00:00:00.000Z', + versions: { '1.0.0': {} } + } + + const packument = new Packument(packumentData) + + assert.strictEqual(packument.name, 'example-package') + assert.deepStrictEqual(packument.distTags, { latest: '1.0.0' }) + assert.strictEqual(packument.modified, '2023-10-01T00:00:00.000Z') + assert.deepStrictEqual(packument.versions, { '1.0.0': {} }) + }) + + it('should handle dist-tags correctly', function () { + const packumentData = { + name: 'example-package', + 'dist-tags': { latest: '1.0.0' }, + modified: '2023-10-01T00:00:00.000Z', + versions: { '1.0.0': {} } + } + + const packument = new Packument(packumentData) + + assert.deepStrictEqual(packument.distTags, { latest: '1.0.0' }) + }) +})