Skip to content

Commit

Permalink
feat(publish): Publish command uses publishConfig.access in package.j…
Browse files Browse the repository at this point in the history
…son (#5290)

* feat(publish): Publish command uses publishConfig.access in package.json

For npm compatability, `yarn publish` should check `publishConfig.access` in package.json and use it
as if the `--access` option was passed.

#5279

* WIP: CI test failure debugging

* WIP: CI test failure debugging

* WIP: CI test failure debugging

* fix CI errors by mocking npm password prompt

* use jest expect().toBeCalledWith() for publish command tests
  • Loading branch information
rally25rs authored and arcanis committed Jan 30, 2018
1 parent aa855c5 commit aa200e4
Show file tree
Hide file tree
Showing 5 changed files with 131 additions and 2 deletions.
10 changes: 10 additions & 0 deletions __tests__/__mocks__/npm-registry.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/* @flow */

import Registry from '../../src/registries/base-registry.js';
import type {RegistryRequestOptions} from '../../src/registries/base-registry.js';

export default class NpmRegistry extends Registry {
request(pathname: string, opts?: RegistryRequestOptions = {}, packageName: ?string): Promise<*> {
return new Promise(resolve => resolve());
}
}
101 changes: 101 additions & 0 deletions __tests__/commands/publish.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
/* @flow */

import {run as buildRun} from './_helpers.js';
import {run as publish} from '../../src/cli/commands/publish.js';
import {ConsoleReporter} from '../../src/reporters/index.js';

const path = require('path');

const fixturesLoc = path.join(__dirname, '..', 'fixtures', 'publish');

const setupMocks = function(config) {
// Mock actual network request so that no package is actually published.
// $FlowFixMe
config.registries.npm.request = jest.fn();
config.registries.npm.request.mockReturnValue(
new Promise(resolve => {
resolve({status: 200});
}),
);

// Mock the npm login name. Otherwise yarn will prompt for it and break CI.
// $FlowFixMe
config.registries.npm.getAuth = jest.fn();
config.registries.npm.getAuth.mockReturnValue('test');
};

const runPublish = buildRun.bind(
null,
ConsoleReporter,
fixturesLoc,
async (args, flags, config, reporter, lockfile, getStdout): Promise<string> => {
setupMocks(config);
await publish(config, reporter, flags, args);
return getStdout();
},
);

test.concurrent('publish should default access to undefined', () => {
return runPublish([], {newVersion: '0.0.1'}, 'minimal', config => {
expect(config.registries.npm.request).toBeCalledWith(
expect.any(String),
expect.objectContaining({
body: expect.objectContaining({
access: undefined,
}),
}),
);
});
});

test.concurrent('publish should accept `--access restricted` argument', () => {
return runPublish([], {newVersion: '0.0.1', access: 'restricted'}, 'minimal', config => {
expect(config.registries.npm.request).toBeCalledWith(
expect.any(String),
expect.objectContaining({
body: expect.objectContaining({
access: 'restricted',
}),
}),
);
});
});

test.concurrent('publish should accept `--access public` argument', () => {
return runPublish([], {newVersion: '0.0.1', access: 'public'}, 'minimal', config => {
expect(config.registries.npm.request).toBeCalledWith(
expect.any(String),
expect.objectContaining({
body: expect.objectContaining({
access: 'public',
}),
}),
);
});
});

test.concurrent('publish should use publishConfig.access in package manifest', () => {
return runPublish([], {newVersion: '0.0.1'}, 'public', config => {
expect(config.registries.npm.request).toBeCalledWith(
expect.any(String),
expect.objectContaining({
body: expect.objectContaining({
access: 'public',
}),
}),
);
});
});

test.concurrent('publish should allow `--access` to override publishConfig.access', () => {
return runPublish([], {newVersion: '0.0.1', access: 'restricted'}, 'public', config => {
expect(config.registries.npm.request).toBeCalledWith(
expect.any(String),
expect.objectContaining({
body: expect.objectContaining({
access: 'restricted',
}),
}),
);
});
});
4 changes: 4 additions & 0 deletions __tests__/fixtures/publish/minimal/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"name": "test",
"version": "0.0.0"
}
7 changes: 7 additions & 0 deletions __tests__/fixtures/publish/public/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"name": "test",
"version": "0.0.0",
"publishConfig": {
"access": "public"
}
}
11 changes: 9 additions & 2 deletions src/cli/commands/publish.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,15 @@ export function hasWrapper(commander: Object, args: Array<string>): boolean {
}

async function publish(config: Config, pkg: any, flags: Object, dir: string): Promise<void> {
let access = flags.access;

// if no access level is provided, check package.json for `publishConfig.access`
// see: https://docs.npmjs.com/files/package.json#publishconfig
if (!access && pkg && pkg.publishConfig && pkg.publishConfig.access) {
access = pkg.publishConfig.access;
}

// validate access argument
const access = flags.access;
if (access && access !== 'public' && access !== 'restricted') {
throw new MessageError(config.reporter.lang('invalidAccess'));
}
Expand Down Expand Up @@ -69,7 +76,7 @@ async function publish(config: Config, pkg: any, flags: Object, dir: string): Pr
// create body
const root = {
_id: pkg.name,
access: flags.access,
access,
name: pkg.name,
description: pkg.description,
'dist-tags': {
Expand Down

0 comments on commit aa200e4

Please sign in to comment.