155 lines
4.6 KiB
JavaScript
155 lines
4.6 KiB
JavaScript
import { describe, expect, test } from 'bun:test';
|
|||
|
|
import * as spec from './plugin-spec.js';
|
||
|
|
|
||
|
|
describe('parseNpmSpec', () => {
|
||
|
|
test('unscoped: no version', () => {
|
||
|
|
expect(spec.parseNpmSpec('foo')).toEqual({ name: 'foo', version: null });
|
||
|
|
});
|
||
|
|
|
||
|
|
test('unscoped: exact version', () => {
|
||
|
|
expect(spec.parseNpmSpec('foo@1.2.3')).toEqual({ name: 'foo', version: '1.2.3' });
|
||
|
|
});
|
||
|
|
|
||
|
|
test('unscoped: range version', () => {
|
||
|
|
expect(spec.parseNpmSpec('foo@^1.2.0')).toEqual({ name: 'foo', version: '^1.2.0' });
|
||
|
|
});
|
||
|
|
|
||
|
|
test('unscoped: dist-tag', () => {
|
||
|
|
expect(spec.parseNpmSpec('foo@latest')).toEqual({ name: 'foo', version: 'latest' });
|
||
|
|
});
|
||
|
|
|
||
|
|
test('scoped: no version', () => {
|
||
|
|
expect(spec.parseNpmSpec('@scope/foo')).toEqual({ name: '@scope/foo', version: null });
|
||
|
|
});
|
||
|
|
|
||
|
|
test('scoped: exact version', () => {
|
||
|
|
expect(spec.parseNpmSpec('@scope/foo@1.2.3')).toEqual({ name: '@scope/foo', version: '1.2.3' });
|
||
|
|
});
|
||
|
|
|
||
|
|
test('scoped: dist-tag', () => {
|
||
|
|
expect(spec.parseNpmSpec('@scope/foo@beta')).toEqual({ name: '@scope/foo', version: 'beta' });
|
||
|
|
});
|
||
|
|
|
||
|
|
test('malformed: empty string', () => {
|
||
|
|
expect(spec.parseNpmSpec('')).toEqual({ malformed: true, raw: '' });
|
||
|
|
});
|
||
|
|
|
||
|
|
test('malformed: bare @', () => {
|
||
|
|
expect(spec.parseNpmSpec('@')).toEqual({ malformed: true, raw: '@' });
|
||
|
|
});
|
||
|
|
|
||
|
|
test('malformed: @@', () => {
|
||
|
|
expect(spec.parseNpmSpec('@@')).toEqual({ malformed: true, raw: '@@' });
|
||
|
|
});
|
||
|
|
|
||
|
|
test('malformed: empty version after @', () => {
|
||
|
|
expect(spec.parseNpmSpec('foo@')).toEqual({ malformed: true, raw: 'foo@' });
|
||
|
|
});
|
||
|
|
|
||
|
|
test('malformed: scoped empty name after slash', () => {
|
||
|
|
expect(spec.parseNpmSpec('@scope/')).toEqual({ malformed: true, raw: '@scope/' });
|
||
|
|
});
|
||
|
|
|
||
|
|
test('malformed: scoped empty version', () => {
|
||
|
|
expect(spec.parseNpmSpec('@scope/foo@')).toEqual({ malformed: true, raw: '@scope/foo@' });
|
||
|
|
});
|
||
|
|
|
||
|
|
test('malformed: null input', () => {
|
||
|
|
expect(spec.parseNpmSpec(null)).toEqual({ malformed: true, raw: 'null' });
|
||
|
|
});
|
||
|
|
|
||
|
|
test('malformed: undefined input', () => {
|
||
|
|
expect(spec.parseNpmSpec(undefined)).toEqual({ malformed: true, raw: 'undefined' });
|
||
|
|
});
|
||
|
|
|
||
|
|
test('malformed: number input', () => {
|
||
|
|
expect(spec.parseNpmSpec(42)).toEqual({ malformed: true, raw: '42' });
|
||
|
|
});
|
||
|
|
|
||
|
|
test('malformed: array input', () => {
|
||
|
|
expect(spec.parseNpmSpec(['foo'])).toEqual({ malformed: true, raw: 'foo' });
|
||
|
|
});
|
||
|
|
|
||
|
|
test('malformed: object input', () => {
|
||
|
|
expect(spec.parseNpmSpec({})).toEqual({ malformed: true, raw: '[object Object]' });
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
describe('isExactSemver', () => {
|
||
|
|
test('plain semver', () => {
|
||
|
|
expect(spec.isExactSemver('1.2.3')).toBe(true);
|
||
|
|
});
|
||
|
|
|
||
|
|
test('semver with pre-release', () => {
|
||
|
|
expect(spec.isExactSemver('1.2.3-beta.1')).toBe(true);
|
||
|
|
});
|
||
|
|
|
||
|
|
test('semver with build metadata', () => {
|
||
|
|
expect(spec.isExactSemver('1.2.3+build.5')).toBe(true);
|
||
|
|
});
|
||
|
|
|
||
|
|
test('range: caret', () => {
|
||
|
|
expect(spec.isExactSemver('^1.2.0')).toBe(false);
|
||
|
|
});
|
||
|
|
|
||
|
|
test('dist-tag', () => {
|
||
|
|
expect(spec.isExactSemver('latest')).toBe(false);
|
||
|
|
});
|
||
|
|
|
||
|
|
test('empty string', () => {
|
||
|
|
expect(spec.isExactSemver('')).toBe(false);
|
||
|
|
});
|
||
|
|
|
||
|
|
test('partial: major.minor only', () => {
|
||
|
|
expect(spec.isExactSemver('1.2')).toBe(false);
|
||
|
|
});
|
||
|
|
|
||
|
|
test('partial: major only', () => {
|
||
|
|
expect(spec.isExactSemver('1')).toBe(false);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
describe('parsePathSpec', () => {
|
||
|
|
test('identifies Windows absolute paths as path specs', () => {
|
||
|
|
expect(spec.isPathSpec('C:\\Users\\me\\plugin.js')).toBe(true);
|
||
|
|
expect(spec.isPathSpec('\\\\server\\share\\plugin.js')).toBe(true);
|
||
|
|
expect(spec.isPathSpec('@scope/plugin')).toBe(false);
|
||
|
|
});
|
||
|
|
|
||
|
|
test('tilde home shorthand with subpath', () => {
|
||
|
|
expect(spec.parsePathSpec('~/x.js', { homedir: '/home/u', cwd: '/p' })).toEqual({
|
||
|
|
absolutePath: '/home/u/x.js',
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
test('bare tilde = homedir', () => {
|
||
|
|
expect(spec.parsePathSpec('~', { homedir: '/home/u', cwd: '/p' })).toEqual({
|
||
|
|
absolutePath: '/home/u',
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
test('relative ./', () => {
|
||
|
|
expect(spec.parsePathSpec('./x.js', { homedir: '/home/u', cwd: '/p' })).toEqual({
|
||
|
|
absolutePath: '/p/x.js',
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
test('relative ../', () => {
|
||
|
|
expect(spec.parsePathSpec('../x.js', { homedir: '/home/u', cwd: '/p/a' })).toEqual({
|
||
|
|
absolutePath: '/p/x.js',
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
test('absolute path passthrough', () => {
|
||
|
|
expect(spec.parsePathSpec('/abs/x.js', { homedir: '/home/u', cwd: '/p' })).toEqual({
|
||
|
|
absolutePath: '/abs/x.js',
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
test('Windows absolute path passthrough', () => {
|
||
|
|
expect(spec.parsePathSpec('C:\\Users\\me\\plugin.js', { homedir: '/home/u', cwd: '/p' })).toEqual({
|
||
|
|
absolutePath: 'C:\\Users\\me\\plugin.js',
|
||
|
|
});
|
||
|
|
});
|
||
|
|
});
|