|
| 1 | +// Copyright (c) Microsoft. All rights reserved. |
| 2 | + |
| 3 | +const { describe, it } = require('node:test'); |
| 4 | +const assert = require('node:assert/strict'); |
| 5 | + |
| 6 | +const checkTeamMembership = require('../scripts/check_team_membership.js'); |
| 7 | + |
| 8 | +const context = { repo: { owner: 'microsoft', repo: 'semantic-kernel' } }; |
| 9 | + |
| 10 | +function githubWithMembership(membership, username = 'contributor') { |
| 11 | + return { |
| 12 | + rest: { |
| 13 | + pulls: { |
| 14 | + get: async (params) => { |
| 15 | + assert.deepEqual(params, { ...context.repo, pull_number: 42 }); |
| 16 | + return { data: { user: { login: 'contributor' } } }; |
| 17 | + }, |
| 18 | + }, |
| 19 | + teams: { |
| 20 | + getByName: async (params) => { |
| 21 | + assert.deepEqual(params, { org: 'microsoft', team_slug: 'developers' }); |
| 22 | + }, |
| 23 | + getMembershipForUserInOrg: async (params) => { |
| 24 | + assert.deepEqual(params, { |
| 25 | + org: 'microsoft', |
| 26 | + team_slug: 'developers', |
| 27 | + username, |
| 28 | + }); |
| 29 | + if (membership instanceof Error) throw membership; |
| 30 | + return { data: { state: membership } }; |
| 31 | + }, |
| 32 | + }, |
| 33 | + }, |
| 34 | + }; |
| 35 | +} |
| 36 | + |
| 37 | +describe('Review requester team membership', () => { |
| 38 | + const options = { context, teamSlug: 'developers', prNumber: '42' }; |
| 39 | + |
| 40 | + it('uses the PR author from the event on automatic runs', async () => { |
| 41 | + const github = githubWithMembership('active'); |
| 42 | + github.rest.pulls.get = async () => { |
| 43 | + throw new Error('Should not look up the PR when the event includes its author'); |
| 44 | + }; |
| 45 | + assert.deepEqual( |
| 46 | + await checkTeamMembership({ |
| 47 | + ...options, |
| 48 | + context: { ...context, payload: { pull_request: { user: { login: 'contributor' } } } }, |
| 49 | + github, |
| 50 | + }), |
| 51 | + { author: 'contributor', isTeamMember: true }, |
| 52 | + ); |
| 53 | + }); |
| 54 | + |
| 55 | + it('uses the initiator on manual runs, even if the PR author is external', async () => { |
| 56 | + const github = githubWithMembership('active', 'maintainer'); |
| 57 | + github.rest.pulls.get = async () => { |
| 58 | + throw new Error('Should not look up the PR author on manual runs'); |
| 59 | + }; |
| 60 | + assert.deepEqual( |
| 61 | + await checkTeamMembership({ ...options, github, username: 'maintainer' }), |
| 62 | + { author: 'maintainer', isTeamMember: true }, |
| 63 | + ); |
| 64 | + assert.deepEqual( |
| 65 | + await checkTeamMembership({ |
| 66 | + ...options, |
| 67 | + github: githubWithMembership(Object.assign(new Error('Not Found'), { status: 404 }), 'outsider'), |
| 68 | + username: 'outsider', |
| 69 | + }), |
| 70 | + { author: 'outsider', isTeamMember: false }, |
| 71 | + ); |
| 72 | + }); |
| 73 | + |
| 74 | + it('accepts an active team member', async () => { |
| 75 | + assert.deepEqual( |
| 76 | + await checkTeamMembership({ ...options, github: githubWithMembership('active') }), |
| 77 | + { author: 'contributor', isTeamMember: true }, |
| 78 | + ); |
| 79 | + }); |
| 80 | + |
| 81 | + it('rejects a pending team member and an outsider', async () => { |
| 82 | + for (const membership of ['pending', Object.assign(new Error('Not Found'), { status: 404 })]) { |
| 83 | + assert.deepEqual( |
| 84 | + await checkTeamMembership({ ...options, github: githubWithMembership(membership) }), |
| 85 | + { author: 'contributor', isTeamMember: false }, |
| 86 | + ); |
| 87 | + } |
| 88 | + }); |
| 89 | + |
| 90 | + it('does not treat API errors or a missing team as nonmembership', async () => { |
| 91 | + await assert.rejects( |
| 92 | + checkTeamMembership({ |
| 93 | + ...options, |
| 94 | + github: githubWithMembership(Object.assign(new Error('Forbidden'), { status: 403 })), |
| 95 | + }), |
| 96 | + /Forbidden/, |
| 97 | + ); |
| 98 | + const github = githubWithMembership('active'); |
| 99 | + github.rest.teams.getByName = async () => { |
| 100 | + throw Object.assign(new Error('Team not found'), { status: 404 }); |
| 101 | + }; |
| 102 | + await assert.rejects(checkTeamMembership({ ...options, github }), /Team not found/); |
| 103 | + }); |
| 104 | + |
| 105 | + it('rejects missing configuration and invalid PR numbers', async () => { |
| 106 | + await assert.rejects( |
| 107 | + checkTeamMembership({ ...options, github: githubWithMembership('active'), teamSlug: '' }), |
| 108 | + /DEVELOPER_TEAM/, |
| 109 | + ); |
| 110 | + for (const prNumber of ['0', '1e2', '9007199254740992']) { |
| 111 | + await assert.rejects( |
| 112 | + checkTeamMembership({ ...options, github: githubWithMembership('active'), prNumber }), |
| 113 | + /valid PR number/, |
| 114 | + ); |
| 115 | + } |
| 116 | + }); |
| 117 | +}); |
0 commit comments