diff --git a/mirage/route-handlers/crates.js b/mirage/route-handlers/crates.js index eea1d76b856..990b1e967aa 100644 --- a/mirage/route-handlers/crates.js +++ b/mirage/route-handlers/crates.js @@ -227,6 +227,11 @@ export function register(server) { }); server.put('/api/v1/crates/:name/owners', (schema, request) => { + let { user } = getSession(schema); + if (!user) { + return new Response(403, {}, { errors: [{ detail: 'must be logged in to perform that action' }] }); + } + let { name } = request.params; let crate = schema.crates.findBy({ name }); @@ -235,17 +240,48 @@ export function register(server) { } const body = JSON.parse(request.requestBody); - const [ownerId] = body.owners; - const user = schema.users.findBy({ login: ownerId }); - if (!user) { - return { errors: [{ detail: `could not find user with login \`${ownerId}\`` }] }; + let users = []; + let teams = []; + let msgs = []; + for (let login of body.owners) { + if (login.includes(':')) { + let team = schema.teams.findBy({ login }); + if (!team) { + return new Response(404, {}, { errors: [{ detail: `could not find team with login \`${login}\`` }] }); + } + + teams.push(team); + msgs.push(`team ${login} has been added as an owner of crate ${crate.name}`); + } else { + let user = schema.users.findBy({ login }); + if (!user) { + return new Response(404, {}, { errors: [{ detail: `could not find user with login \`${login}\`` }] }); + } + + users.push(user); + msgs.push(`user ${login} has been invited to be an owner of crate ${crate.name}`); + } } - return { ok: true }; + for (let team of teams) { + schema.crateOwnerships.create({ crate, team }); + } + + for (let invitee of users) { + schema.crateOwnerInvitations.create({ crate, inviter: user, invitee }); + } + + let msg = msgs.join(','); + return { ok: true, msg }; }); server.delete('/api/v1/crates/:name/owners', (schema, request) => { + let { user } = getSession(schema); + if (!user) { + return new Response(403, {}, { errors: [{ detail: 'must be logged in to perform that action' }] }); + } + let { name } = request.params; let crate = schema.crates.findBy({ name }); diff --git a/tests/adapters/crate-test.js b/tests/adapters/crate-test.js index 4146e6cfaf3..0b4a6722f27 100644 --- a/tests/adapters/crate-test.js +++ b/tests/adapters/crate-test.js @@ -1,8 +1,6 @@ import { module, test } from 'qunit'; -import { setupMirage } from 'ember-cli-mirage/test-support'; - -import { setupTest } from 'crates-io/tests/helpers'; +import { setupMirage, setupTest } from 'crates-io/tests/helpers'; module('Adapter | crate', function (hooks) { setupTest(hooks); diff --git a/tests/helpers/index.js b/tests/helpers/index.js index aaa59798700..b33c551cdb2 100644 --- a/tests/helpers/index.js +++ b/tests/helpers/index.js @@ -3,6 +3,7 @@ import { setupApplicationTest as upstreamSetupApplicationTest } from 'ember-quni import { setupSentryMock } from './sentry'; import setupMirage from './setup-mirage'; +export { default as setupMirage } from './setup-mirage'; export { setupTest, setupRenderingTest } from 'ember-qunit'; // see http://emberjs.github.io/rfcs/0637-customizable-test-setups.html diff --git a/tests/mirage/crates/add-owner-test.js b/tests/mirage/crates/add-owner-test.js new file mode 100644 index 00000000000..05463d2710e --- /dev/null +++ b/tests/mirage/crates/add-owner-test.js @@ -0,0 +1,119 @@ +import { module, test } from 'qunit'; + +import fetch from 'fetch'; + +import { setupTest } from '../../helpers'; +import setupMirage from '../../helpers/setup-mirage'; + +const ADD_USER_BODY = JSON.stringify({ owners: ['john-doe'] }); + +module('Mirage | PUT /api/v1/crates/:name/owners', function (hooks) { + setupTest(hooks); + setupMirage(hooks); + + test('returns 403 if unauthenticated', async function (assert) { + let response = await fetch('/api/v1/crates/foo/owners', { method: 'PUT', body: ADD_USER_BODY }); + assert.strictEqual(response.status, 403); + assert.deepEqual(await response.json(), { + errors: [{ detail: 'must be logged in to perform that action' }], + }); + }); + + test('returns 404 for unknown crates', async function (assert) { + let user = this.server.create('user'); + this.authenticateAs(user); + + let response = await fetch('/api/v1/crates/foo/owners', { method: 'PUT', body: ADD_USER_BODY }); + assert.strictEqual(response.status, 404); + assert.deepEqual(await response.json(), { errors: [{ detail: 'Not Found' }] }); + }); + + test('can add new owner', async function (assert) { + let user = this.server.create('user'); + this.authenticateAs(user); + + let crate = this.server.create('crate', { name: 'foo' }); + this.server.create('crate-ownership', { crate, user }); + + let user2 = this.server.create('user'); + + let body = JSON.stringify({ owners: [user2.login] }); + let response = await fetch('/api/v1/crates/foo/owners', { method: 'PUT', body }); + assert.strictEqual(response.status, 200); + assert.deepEqual(await response.json(), { + ok: true, + msg: 'user user-2 has been invited to be an owner of crate foo', + }); + + let owners = this.server.schema.crateOwnerships.where({ crateId: crate.id }); + assert.strictEqual(owners.length, 1); + assert.strictEqual(owners.models[0].userId, user.id); + + let invites = this.server.schema.crateOwnerInvitations.where({ crateId: crate.id }); + assert.strictEqual(invites.length, 1); + assert.strictEqual(invites.models[0].inviterId, user.id); + assert.strictEqual(invites.models[0].inviteeId, user2.id); + }); + + test('can add team owner', async function (assert) { + let user = this.server.create('user'); + this.authenticateAs(user); + + let crate = this.server.create('crate', { name: 'foo' }); + this.server.create('crate-ownership', { crate, user }); + + let team = this.server.create('team'); + + let body = JSON.stringify({ owners: [team.login] }); + let response = await fetch('/api/v1/crates/foo/owners', { method: 'PUT', body }); + assert.strictEqual(response.status, 200); + assert.deepEqual(await response.json(), { + ok: true, + msg: 'team github:rust-lang:team-1 has been added as an owner of crate foo', + }); + + let owners = this.server.schema.crateOwnerships.where({ crateId: crate.id }); + assert.strictEqual(owners.length, 2); + assert.strictEqual(owners.models[0].userId, user.id); + assert.strictEqual(owners.models[0].teamId, null); + assert.strictEqual(owners.models[1].userId, null); + assert.strictEqual(owners.models[1].teamId, user.id); + + let invites = this.server.schema.crateOwnerInvitations.where({ crateId: crate.id }); + assert.strictEqual(invites.length, 0); + }); + + test('can add multiple owners', async function (assert) { + let user = this.server.create('user'); + this.authenticateAs(user); + + let crate = this.server.create('crate', { name: 'foo' }); + this.server.create('crate-ownership', { crate, user }); + + let team = this.server.create('team'); + let user2 = this.server.create('user'); + let user3 = this.server.create('user'); + + let body = JSON.stringify({ owners: [user2.login, team.login, user3.login] }); + let response = await fetch('/api/v1/crates/foo/owners', { method: 'PUT', body }); + assert.strictEqual(response.status, 200); + assert.deepEqual(await response.json(), { + ok: true, + msg: 'user user-2 has been invited to be an owner of crate foo,team github:rust-lang:team-1 has been added as an owner of crate foo,user user-3 has been invited to be an owner of crate foo', + }); + + let owners = this.server.schema.crateOwnerships.where({ crateId: crate.id }); + assert.strictEqual(owners.length, 2); + assert.strictEqual(owners.models[0].userId, user.id); + assert.strictEqual(owners.models[0].teamId, null); + assert.strictEqual(owners.models[1].userId, null); + assert.strictEqual(owners.models[1].teamId, user.id); + + let invites = this.server.schema.crateOwnerInvitations.where({ crateId: crate.id }); + assert.strictEqual(invites.length, 2); + assert.strictEqual(invites.models[0].inviterId, user.id); + assert.strictEqual(invites.models[0].inviteeId, user2.id); + assert.strictEqual(invites.models[1].inviterId, user.id); + assert.strictEqual(invites.models[1].inviteeId, user3.id); + }); +}); diff --git a/tests/models/crate-test.js b/tests/models/crate-test.js index 03575002075..d722c12d9cd 100644 --- a/tests/models/crate-test.js +++ b/tests/models/crate-test.js @@ -2,9 +2,7 @@ import { module, test } from 'qunit'; import AdapterError from '@ember-data/adapter/error'; -import { setupMirage } from 'ember-cli-mirage/test-support'; - -import { setupTest } from 'crates-io/tests/helpers'; +import { setupMirage, setupTest } from 'crates-io/tests/helpers'; module('Model | Crate', function (hooks) { setupTest(hooks); @@ -17,17 +15,23 @@ module('Model | Crate', function (hooks) { module('inviteOwner()', function () { test('happy path', async function (assert) { let user = this.server.create('user'); + this.authenticateAs(user); let crate = this.server.create('crate'); this.server.create('version', { crate }); + let user2 = this.server.create('user'); + let crateRecord = await this.store.findRecord('crate', crate.name); - let result = await crateRecord.inviteOwner(user.login); - assert.deepEqual(result, { ok: true }); + let result = await crateRecord.inviteOwner(user2.login); + assert.deepEqual(result, { ok: true, msg: 'user user-2 has been invited to be an owner of crate crate-0' }); }); test('error handling', async function (assert) { + let user = this.server.create('user'); + this.authenticateAs(user); + let crate = this.server.create('crate'); this.server.create('version', { crate }); @@ -43,17 +47,23 @@ module('Model | Crate', function (hooks) { module('removeOwner()', function () { test('happy path', async function (assert) { let user = this.server.create('user'); + this.authenticateAs(user); let crate = this.server.create('crate'); this.server.create('version', { crate }); + let user2 = this.server.create('user'); + let crateRecord = await this.store.findRecord('crate', crate.name); - let result = await crateRecord.removeOwner(user.login); + let result = await crateRecord.removeOwner(user2.login); assert.deepEqual(result, { ok: true, msg: 'owners successfully removed' }); }); test('error handling', async function (assert) { + let user = this.server.create('user'); + this.authenticateAs(user); + let crate = this.server.create('crate'); this.server.create('version', { crate }); diff --git a/tests/models/version-test.js b/tests/models/version-test.js index fd9e8fd66ac..34601ed9757 100644 --- a/tests/models/version-test.js +++ b/tests/models/version-test.js @@ -1,14 +1,10 @@ -import { setupTest } from 'ember-qunit'; import { module, test } from 'qunit'; -import { setupMirage } from 'ember-cli-mirage/test-support'; - -import { setupFakeTimers } from '../helpers/fake-timers'; +import { setupMirage, setupTest } from 'crates-io/tests/helpers'; module('Model | Version', function (hooks) { setupTest(hooks); setupMirage(hooks); - setupFakeTimers(hooks); hooks.beforeEach(function () { this.store = this.owner.lookup('service:store'); diff --git a/tests/services/playground-test.js b/tests/services/playground-test.js index c8cc4d3296b..bba9e018bad 100644 --- a/tests/services/playground-test.js +++ b/tests/services/playground-test.js @@ -1,8 +1,6 @@ import { module, test } from 'qunit'; -import { setupMirage } from 'ember-cli-mirage/test-support'; - -import { setupTest } from 'crates-io/tests/helpers'; +import { setupMirage, setupTest } from 'crates-io/tests/helpers'; module('Service | Playground', function (hooks) { setupTest(hooks);