Skip to content

Commit

Permalink
Add more tests
Browse files Browse the repository at this point in the history
Signed-off-by: Oliver Sand <oliver.sand@sda-se.com>
  • Loading branch information
Fox32 committed Oct 21, 2021
1 parent fc5150d commit 8ba7481
Show file tree
Hide file tree
Showing 7 changed files with 342 additions and 14 deletions.
2 changes: 1 addition & 1 deletion plugins/catalog-backend-module-msgraph/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ builder.addEntityProvider(msGraphOrgEntityProvider);
// Trigger a read every 5 minutes
useHotCleanup(
module,
runPeriodically(async () => msGraphOrgEntityProvider.read(), 5 * 60 * 1000),
runPeriodically(() => msGraphOrgEntityProvider.read(), 5 * 60 * 1000),
);
```

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,4 +72,21 @@ describe('readMicrosoftGraphConfig', () => {
];
expect(actual).toEqual(expected);
});

it('should fail if both userFilter and userGroupMemberFilter are set', () => {
const config = {
providers: [
{
target: 'target',
tenantId: 'tenantId',
clientId: 'clientId',
clientSecret: 'clientSecret',
authority: 'https://login.example.com/',
userFilter: 'accountEnabled eq true',
userGroupMemberFilter: 'any',
},
],
};
expect(() => readMicrosoftGraphConfig(new ConfigReader(config))).toThrow();
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,12 @@ export function readMicrosoftGraphConfig(
);
const groupFilter = providerConfig.getOptionalString('groupFilter');

if (userFilter && userGroupMemberFilter) {
throw new Error(
`userFilter and userGroupMemberFilter are mutually exclusive, only one can be specified.`,
);
}

providers.push({
target,
authority,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
/*
* Copyright 2021 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { getVoidLogger } from '@backstage/backend-common';
import {
GroupEntity,
LOCATION_ANNOTATION,
ORIGIN_LOCATION_ANNOTATION,
UserEntity,
} from '@backstage/catalog-model';
import { EntityProviderConnection } from '@backstage/plugin-catalog-backend';
import {
MicrosoftGraphClient,
MICROSOFT_GRAPH_USER_ID_ANNOTATION,
readMicrosoftGraphOrg,
} from '../microsoftGraph';
import {
MicrosoftGraphOrgEntityProvider,
withLocations,
} from './MicrosoftGraphOrgEntityProvider';

jest.mock('../microsoftGraph', () => {
return {
...jest.requireActual('../microsoftGraph'),
readMicrosoftGraphOrg: jest.fn(),
};
});

const readMicrosoftGraphOrgMocked = readMicrosoftGraphOrg as jest.Mock<
Promise<{ users: UserEntity[]; groups: GroupEntity[] }>
>;

describe('MicrosoftGraphOrgEntityProvider', () => {
afterEach(() => jest.resetAllMocks());

it('should apply mutation', async () => {
jest
.spyOn(MicrosoftGraphClient, 'create')
.mockReturnValue({} as unknown as MicrosoftGraphClient);

readMicrosoftGraphOrgMocked.mockResolvedValue({
users: [
{
apiVersion: 'backstage.io/v1alpha1',
kind: 'User',
metadata: {
name: 'u1',
},
spec: {
memberOf: [],
},
},
],
groups: [
{
apiVersion: 'backstage.io/v1alpha1',
kind: 'Group',
metadata: {
name: 'g1',
},
spec: {
type: 'team',
children: [],
},
},
],
});

const entityProviderConnection: EntityProviderConnection = {
applyMutation: jest.fn(),
};
const provider = new MicrosoftGraphOrgEntityProvider({
id: 'test',
logger: getVoidLogger(),
provider: {
target: 'https://example.com',
tenantId: 'tenant',
clientId: 'clientid',
clientSecret: 'clientsecret',
},
});

provider.connect(entityProviderConnection);

await provider.read();

expect(entityProviderConnection.applyMutation).toBeCalledWith({
entities: [
{
entity: {
apiVersion: 'backstage.io/v1alpha1',
kind: 'User',
metadata: {
annotations: {
'backstage.io/managed-by-location': 'msgraph:test/u1',
'backstage.io/managed-by-origin-location': 'msgraph:test/u1',
},
name: 'u1',
},
spec: {
memberOf: [],
},
},
locationKey: 'msgraph-org-provider:test',
},
{
entity: {
apiVersion: 'backstage.io/v1alpha1',
kind: 'Group',
metadata: {
annotations: {
'backstage.io/managed-by-location': 'msgraph:test/g1',
'backstage.io/managed-by-origin-location': 'msgraph:test/g1',
},
name: 'g1',
},
spec: {
children: [],
type: 'team',
},
},
locationKey: 'msgraph-org-provider:test',
},
],
type: 'full',
});
});
});

describe('withLocations', () => {
it('should set location annotations', () => {
expect(
withLocations('test', {
apiVersion: 'backstage.io/v1alpha1',
kind: 'User',
metadata: {
name: 'u1',
annotations: {
[MICROSOFT_GRAPH_USER_ID_ANNOTATION]: 'uid',
},
},
spec: {
memberOf: [],
},
}),
).toEqual({
apiVersion: 'backstage.io/v1alpha1',
kind: 'User',
metadata: {
name: 'u1',
annotations: {
[MICROSOFT_GRAPH_USER_ID_ANNOTATION]: 'uid',
[LOCATION_ANNOTATION]: 'msgraph:test/uid',
[ORIGIN_LOCATION_ANNOTATION]: 'msgraph:test/uid',
},
},
spec: {
memberOf: [],
},
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -66,12 +66,6 @@ export class MicrosoftGraphOrgEntityProvider implements EntityProvider {
);
}

if (provider.userFilter && provider.userGroupMemberFilter) {
throw new Error(
`userFilter and userGroupMemberFilter are mutually exclusive, only one can be specified.`,
);
}

const logger = options.logger.child({
target: options.target,
});
Expand Down Expand Up @@ -166,7 +160,7 @@ function trackProgress(logger: Logger) {
}

// Makes sure that emitted entities have a proper location based on their uuid
function withLocations(providerId: string, entity: Entity): Entity {
export function withLocations(providerId: string, entity: Entity): Entity {
const uuid =
entity.metadata.annotations?.[MICROSOFT_GRAPH_USER_ID_ANNOTATION] ||
entity.metadata.annotations?.[MICROSOFT_GRAPH_GROUP_ID_ANNOTATION] ||
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
/*
* Copyright 2020 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import { getVoidLogger } from '@backstage/backend-common';
import { GroupEntity, UserEntity } from '@backstage/catalog-model';
import { MicrosoftGraphClient, readMicrosoftGraphOrg } from '../microsoftGraph';
import { MicrosoftGraphOrgReaderProcessor } from './MicrosoftGraphOrgReaderProcessor';

jest.mock('../microsoftGraph', () => {
return {
...jest.requireActual('../microsoftGraph'),
readMicrosoftGraphOrg: jest.fn(),
};
});

const readMicrosoftGraphOrgMocked = readMicrosoftGraphOrg as jest.Mock<
Promise<{ users: UserEntity[]; groups: GroupEntity[] }>
>;

describe('MicrosoftGraphOrgReaderProcessor', () => {
const emit = jest.fn();
let processor: MicrosoftGraphOrgReaderProcessor;

beforeEach(() => {
processor = new MicrosoftGraphOrgReaderProcessor({
providers: [
{
target: 'https://example.com',
tenantId: 'tenant',
clientId: 'clientid',
clientSecret: 'clientsecret',
},
],
logger: getVoidLogger(),
});

jest
.spyOn(MicrosoftGraphClient, 'create')
.mockReturnValue({} as unknown as MicrosoftGraphClient);
});

afterEach(() => jest.resetAllMocks());

it('should process microsoft-graph-org locations', async () => {
const location = {
type: 'microsoft-graph-org',
target: 'https://example.com',
};

readMicrosoftGraphOrgMocked.mockResolvedValue({
users: [
{
apiVersion: 'backstage.io/v1alpha1',
kind: 'User',
metadata: {
name: 'u1',
},
spec: {
memberOf: [],
},
},
],
groups: [
{
apiVersion: 'backstage.io/v1alpha1',
kind: 'Group',
metadata: {
name: 'g1',
},
spec: {
type: 'team',
children: [],
},
},
],
});

const processed = await processor.readLocation(location, false, emit);

expect(processed).toBe(true);
expect(emit).toBeCalledTimes(2);
expect(emit).toBeCalledWith({
entity: {
apiVersion: 'backstage.io/v1alpha1',
kind: 'Group',
metadata: {
name: 'g1',
},
spec: {
children: [],
type: 'team',
},
},
location: {
target: 'https://example.com',
type: 'microsoft-graph-org',
},
type: 'entity',
});
expect(emit).toBeCalledWith({
entity: {
apiVersion: 'backstage.io/v1alpha1',
kind: 'User',
metadata: {
name: 'u1',
},
spec: {
memberOf: [],
},
},
location: {
target: 'https://example.com',
type: 'microsoft-graph-org',
},
type: 'entity',
});
});

it('should ignore other locations', async () => {
const location = {
type: 'url',
target: 'https://example.com',
};

const processed = await processor.readLocation(location, false, emit);

expect(processed).toBe(false);
expect(emit).toBeCalledTimes(0);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -90,12 +90,6 @@ export class MicrosoftGraphOrgReaderProcessor implements CatalogProcessor {
);
}

if (provider.userFilter && provider.userGroupMemberFilter) {
throw new Error(
`userFilter and userGroupMemberFilter are mutually exclusive, only one can be specified.`,
);
}

// Read out all of the raw data
const startTimestamp = Date.now();
this.logger.info('Reading Microsoft Graph users and groups');
Expand Down

0 comments on commit 8ba7481

Please sign in to comment.