Skip to content

Commit

Permalink
test(synchronizer): introduce synchronizer tests
Browse files Browse the repository at this point in the history
  • Loading branch information
f1ames committed Aug 11, 2023
1 parent c4fc677 commit b28e8bf
Show file tree
Hide file tree
Showing 4 changed files with 362 additions and 18 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
plugins:
open-policy-agent: false
resource-links: true
yaml-syntax: true
kubernetes-schema: true
pod-security-standards: true
practices: true
metadata: false
329 changes: 329 additions & 0 deletions packages/synchronizer/src/__tests__/synchronizer.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,329 @@
import {dirname, resolve} from 'path';
import {fileURLToPath} from 'url';
import {rm, mkdir, cp} from 'fs/promises';
import sinon from 'sinon';
import {assert} from 'chai';
import {createDefaultMonokleSynchronizer} from '../createDefaultMonokleSynchronizer.js';
import {StorageHandlerPolicy} from '../handlers/storageHandlerPolicy.js';

const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);

describe('Synchronizer Tests', () => {
const stubs: sinon.SinonStub[] = [];

before(async () => {
await cleanupTmpConfigDir();
});

afterEach(async () => {
if (stubs.length) {
stubs.forEach(stub => stub.restore());
}

await cleanupTmpConfigDir();
});

describe('getPolicy', () => {
it('returns no policy if there is no policy file (from path)', async () => {
const storagePath = await createTmpConfigDir();
const authenticator = createDefaultMonokleSynchronizer(new StorageHandlerPolicy(storagePath));

const policy = await authenticator.getPolicy(storagePath);

assert.isObject(policy);
assert.isFalse(policy.valid);
assert.isEmpty(policy.path);
assert.isEmpty(policy.policy);
});

it('returns no policy if there is no policy file (from git data)', async () => {
const storagePath = await createTmpConfigDir();
const authenticator = createDefaultMonokleSynchronizer(new StorageHandlerPolicy(storagePath));

const policy = await authenticator.getPolicy({
provider: 'github',
remote: 'origin',
owner: 'kubeshop',
name: 'monokle-core',
});

assert.isObject(policy);
assert.isFalse(policy.valid);
assert.isEmpty(policy.path);
assert.isEmpty(policy.policy);
});

it('returns policy if there is policy file (from path)', async () => {
const storagePath = await createTmpConfigDir('github-kubeshop-monokle-core.policy.yaml');
const authenticator = createDefaultMonokleSynchronizer(new StorageHandlerPolicy(storagePath));

const getRepoRemoteDataStub = sinon.stub((authenticator as any).gitHandler, 'getRepoRemoteData').resolves({
provider: 'github',
remote: 'origin',
owner: 'kubeshop',
name: 'monokle-core',
});
stubs.push(getRepoRemoteDataStub);

const policy = await authenticator.getPolicy(storagePath);

assert.isObject(policy);
assert.isTrue(policy.valid);
assert.isNotEmpty(policy.path);
assert.match(policy.path, /github-kubeshop-monokle-core.policy.yaml$/);
assert.isNotEmpty(policy.policy);
});

it('returns policy if there is policy file (from git data)', async () => {
const storagePath = await createTmpConfigDir('github-kubeshop-monokle-core.policy.yaml');
const authenticator = createDefaultMonokleSynchronizer(new StorageHandlerPolicy(storagePath));

const policy = await authenticator.getPolicy({
provider: 'github',
remote: 'origin',
owner: 'kubeshop',
name: 'monokle-core',
});

assert.isObject(policy);
assert.isTrue(policy.valid);
assert.isNotEmpty(policy.path);
assert.match(policy.path, /github-kubeshop-monokle-core.policy.yaml$/);
assert.isNotEmpty(policy.policy);
assert.isNotEmpty(policy.policy.plugins);
});

it('throws error when no access token provided with forceRefetch set', async () => {
try {
const storagePath = await createTmpConfigDir();
const authenticator = createDefaultMonokleSynchronizer(new StorageHandlerPolicy(storagePath));

await authenticator.getPolicy(storagePath, true);

assert.fail('Should have thrown error.');
} catch (err: any) {
assert.match(err.message, /Cannot force refetch without access token/);
}
});

it('refetches policy when forceRefetch set', async() => {
const storagePath = await createTmpConfigDir();
const authenticator = createDefaultMonokleSynchronizer(new StorageHandlerPolicy(storagePath));

const queryApiStub = sinon.stub((authenticator as any).apiHandler, 'queryApi').callsFake(async (...args) => {
const query = args[0] as string;

if (query.includes('query getUser')) {
return {
data: {
me: {
id: 5,
email: '[email protected]',
projects: [
{
project: {
id: 5000,
slug: 'user5-proj',
name: 'User5 Project',
repositories: [
{
id: "user5-proj-policy-id",
projectId: 5000,
provider: "GITHUB",
owner: "kubeshop",
name: "monokle-core",
prChecks: false,
canEnablePrChecks: true
}
],
},
},
],
},
},
};
}

if (query.includes('query getPolicy')) {
return {
data: {
getProject: {
id: 5000,
policy: {
id: "user5-proj-policy-id",
json: {
plugins: {
"pod-security-standards": true,
"yaml-syntax": false,
"resource-links": false,
"kubernetes-schema": false,
practices: true
},
rules: {
"pod-security-standards/host-process": "err",
},
settings: {
"kubernetes-schema": {
schemaVersion: "v1.27.1"
}
}
}
}
}
}
}
}

return {};
});
stubs.push(queryApiStub);

const repoData = {
provider: 'github',
remote: 'origin',
owner: 'kubeshop',
name: 'monokle-core',
};

const policy = await authenticator.getPolicy(repoData);

assert.isFalse(policy.valid);

const newPolicy = await authenticator.getPolicy(repoData, true, 'SAMPLE_ACCESS_TOKEN');

assert.isObject(newPolicy);
assert.isTrue(newPolicy.valid);
assert.isNotEmpty(newPolicy.path);
assert.match(newPolicy.path, /github-kubeshop-monokle-core.policy.yaml$/);
assert.isNotEmpty(newPolicy.policy);
assert.isNotEmpty(newPolicy.policy.plugins);
assert.isNotEmpty(newPolicy.policy.rules);
assert.isNotEmpty(newPolicy.policy.settings);

const getPolicyResult = await authenticator.getPolicy(repoData);

assert.deepEqual(newPolicy, getPolicyResult);
});

it('emits synchronize event after policy is fetched', async () => {
const storagePath = await createTmpConfigDir();
const authenticator = createDefaultMonokleSynchronizer(new StorageHandlerPolicy(storagePath));

const queryApiStub = sinon.stub((authenticator as any).apiHandler, 'queryApi').callsFake(async (...args) => {
const query = args[0] as string;

if (query.includes('query getUser')) {
return {
data: {
me: {
id: 5,
email: '[email protected]',
projects: [
{
project: {
id: 5000,
slug: 'user5-proj',
name: 'User5 Project',
repositories: [
{
id: "user5-proj-policy-id",
projectId: 5000,
provider: "GITHUB",
owner: "kubeshop",
name: "monokle-core",
prChecks: false,
canEnablePrChecks: true
}
],
},
},
],
},
},
};
}

if (query.includes('query getPolicy')) {
return {
data: {
getProject: {
id: 5000,
policy: {
id: "user5-proj-policy-id",
json: {
plugins: {
"pod-security-standards": true,
"yaml-syntax": false,
"resource-links": false,
"kubernetes-schema": false,
practices: true
},
rules: {
"pod-security-standards/host-process": "err",
},
settings: {
"kubernetes-schema": {
schemaVersion: "v1.27.1"
}
}
}
}
}
}
}
}

return {};
});
stubs.push(queryApiStub);

const repoData = {
provider: 'github',
remote: 'origin',
owner: 'kubeshop',
name: 'monokle-core',
};

const result = new Promise(resolve => {
authenticator.on('synchronize', (policy) => {
assert.isObject(policy);
assert.isTrue(policy.valid);
assert.isNotEmpty(policy.path);
assert.match(policy.path, /github-kubeshop-monokle-core.policy.yaml$/);
assert.isNotEmpty(policy.policy);
assert.isNotEmpty(policy.policy.plugins);
assert.isNotEmpty(policy.policy.rules);
assert.isNotEmpty(policy.policy.settings);

resolve(policy);
});
});

await authenticator.getPolicy(repoData, true, 'SAMPLE_ACCESS_TOKEN');

return result;
});
});
});

async function createTmpConfigDir(copyPolicyFixture = '') {
const testDir = resolve(__dirname, './');
const testTmpDir = resolve(testDir, './tmp');
const fixturesSourceDir = resolve(testDir, '../../src/__tests__/fixtures');

await mkdir(testTmpDir, {recursive: true});

if (copyPolicyFixture) {
await cp(resolve(fixturesSourceDir, copyPolicyFixture), resolve(testTmpDir, copyPolicyFixture));
}

return testTmpDir;
}

async function cleanupTmpConfigDir() {
const testDir = resolve(__dirname, './');
const testTmpDir = resolve(testDir, './tmp');

await rm(testTmpDir, {recursive: true, force: true});
}
22 changes: 12 additions & 10 deletions packages/synchronizer/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
export * from './handlers/apiHandler';
export * from './handlers/deviceFlowHandler';
export * from './handlers/gitHandler';
export * from './handlers/storageHandler';
export * from './handlers/storageHandlerAuth';
export * from './handlers/storageHandlerPolicy';
export * from './handlers/apiHandler.js';
export * from './handlers/deviceFlowHandler.js';
export * from './handlers/gitHandler.js';
export * from './handlers/storageHandler.js';
export * from './handlers/storageHandlerAuth.js';
export * from './handlers/storageHandlerPolicy.js';

export * from './utils/authenticator';
export * from './utils/synchronizer';
export * from './utils/authenticator.js';
export * from './utils/synchronizer.js';

export * from './createDefaultMonokleAuthenticator';
export * from './createDefaultMonokleSynchronizer';
export * from './constants.js';

export * from './createDefaultMonokleAuthenticator.js';
export * from './createDefaultMonokleSynchronizer.js';
Loading

0 comments on commit b28e8bf

Please sign in to comment.