Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Proper Unit Test Coverage #46

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 49 additions & 0 deletions tests/OPAPolicy.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import React from 'react';
import { describe, it, expect, vi } from 'vitest';
import { render } from 'ink-testing-library';
import Policy from '../source/commands/opa/policy';
import delay from 'delay';
global.fetch = vi.fn();
const enter = '\r';

describe('OPA Policy Command', () => {
it('should render the policy command', async () => {
const options = {
serverUrl: 'http://localhost:8181',
keyAccount: 'testAccount',
apiKey: 'permit_key_'.concat('a'.repeat(97)),
};
(fetch as any).mockResolvedValueOnce({
ok: true,
json: async () => ({
result: [
{ id: 'policy1', name: 'policyName1' },
{ id: 'policy2', name: 'policyName2' },
],
}),
status: 200,
});
const { stdin, lastFrame } = render(<Policy options={options} />);
expect(lastFrame()?.toString()).toMatch(
'Listing Policies on Opa Server=http://localhost:8181',
);
await delay(50);
expect(lastFrame()?.toString()).toMatch('Showing 2 of 2 policies:');
expect(lastFrame()?.toString()).toMatch('policy1');
expect(lastFrame()?.toString()).toMatch('policy2');
stdin.write(enter);
});
it('should render the policy command with error', async () => {
const options = {
serverUrl: 'http://localhost:8181',
keyAccount: 'testAccount',
};
(fetch as any).mockRejectedValueOnce(new Error('Error'));
const { lastFrame } = render(<Policy options={options} />);
expect(lastFrame()?.toString()).toMatch(
'Listing Policies on Opa Server=http://localhost:8181',
);
await delay(50);
expect(lastFrame()?.toString()).toMatch(/Request failed:/);
});
});
94 changes: 94 additions & 0 deletions tests/PDPCheck.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
import React from 'react';
import { render } from 'ink-testing-library';
import { describe, vi, it, expect, afterEach } from 'vitest';
import delay from 'delay';
import Check from '../source/commands/pdp/check';

global.fetch = vi.fn();

describe('PDP Check Component', () => {
afterEach(() => {
// Clear mock calls after each test
vi.clearAllMocks();
});
it('should render with the given options', async () => {
(fetch as any).mockResolvedValueOnce({
ok: true,
json: async () => ({ allow: true }),
});
const options = {
user: 'testUser',
resource: 'testResource',
action: 'testAction',
tenant: 'testTenant',
keyAccount: 'testKeyAccount',
};

const { lastFrame } = render(<Check options={options} />);
expect(lastFrame()).toMatchInlineSnapshot(`
"Checking user="testUser" action=testAction resource=testResource at tenant=testTenant"
`);
await delay(50);
expect(lastFrame()?.toString()).toContain('ALLOWED');
});
it('should render with the given options', async () => {
(fetch as any).mockResolvedValueOnce({
ok: true,
json: async () => ({ allow: false }),
});
const options = {
user: 'testUser',
resource: 'testResource',
action: 'testAction',
tenant: 'testTenant',
keyAccount: 'testKeyAccount',
};

const { lastFrame } = render(<Check options={options} />);
expect(lastFrame()).toMatchInlineSnapshot(`
"Checking user="testUser" action=testAction resource=testResource at tenant=testTenant"
`);
await delay(50);
expect(lastFrame()?.toString()).toContain('DENIED');
});
it('should render with the given options', async () => {
(fetch as any).mockResolvedValueOnce({
ok: false,
text: async () => 'Error',
});
const options = {
user: 'testUser',
resource: 'testResource',
action: 'testAction',
tenant: 'testTenant',
keyAccount: 'testKeyAccount',
};

const { lastFrame } = render(<Check options={options} />);
expect(lastFrame()).toMatchInlineSnapshot(`
"Checking user="testUser" action=testAction resource=testResource at tenant=testTenant"
`);
await delay(50);
expect(lastFrame()?.toString()).toContain('Error');
});
it('should render with the given options with multiple resource', async () => {
(fetch as any).mockResolvedValueOnce({
ok: true,
json: async () => ({ allow: true }),
});
const options = {
user: 'testUser',
resource: 'testResourceType: testRecsourceKey',
action: 'testAction',
tenant: 'testTenant',
keyAccount: 'testKeyAccount',
};

const { lastFrame } = render(<Check options={options} />);
expect(lastFrame()).toMatchInlineSnapshot(`
"Checking user="testUser" action=testAction resource=testResourceType: testRecsourceKey at
tenant=testTenant"`);
await delay(50);
expect(lastFrame()?.toString()).toContain('ALLOWED');
});
});
11 changes: 11 additions & 0 deletions tests/PDPRun.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import React from 'react';
import { describe, expect, it } from 'vitest';
import { render } from 'ink-testing-library';
import Run from '../source/commands/pdp/run';

describe('PDP Run', () => {
it('Should render the PDP Run command', () => {
const { lastFrame } = render(<Run options={{ opa: 8181 }} />);
expect(lastFrame()?.toString()).toMatch(/Loading Token/);
});
});
44 changes: 44 additions & 0 deletions tests/apiKey.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import React from 'react';
import { render } from 'ink-testing-library';
import ApiKey from '../source/commands/apiKey';
import { describe, it, expect } from 'vitest';
import delay from 'delay';

describe('ApiKey', () => {
it('Should save the key', () => {
const permitKey = 'permit_key_'.concat('a'.repeat(97));
const { lastFrame } = render(
<ApiKey args={['save', permitKey]} options={{ keyAccount: 'test' }} />,
);
expect(lastFrame()).toMatch(/Key saved to secure key store./);
});
it('Should validate the key', () => {
const permitKey = 'permit_key_'.concat('a'.repeat(97));
const { lastFrame } = render(
<ApiKey
args={['validate', permitKey]}
options={{ keyAccount: 'test' }}
/>,
);
expect(lastFrame()).toMatch(/Key is valid./);
});
it('Should read the key', async () => {
const permitKey = 'permit_key_'.concat('a'.repeat(97));
const { lastFrame } = render(
<ApiKey args={['read', permitKey]} options={{ keyAccount: 'test' }} />,
);
await delay(50);
expect(lastFrame()).toMatch(/permit_key_aaaaaaa/);
});
it('Invalid Key', async () => {
const permitKey = 'permit_key'.concat('a'.repeat(97));
const { lastFrame } = render(
<ApiKey
args={['validate', permitKey]}
options={{ keyAccount: 'test' }}
/>,
);
await delay(50);
expect(lastFrame()).toMatch(/Key is not valid./);
});
});
86 changes: 86 additions & 0 deletions tests/components/AuthProvider.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
import React from 'react';
import { render } from 'ink-testing-library';
import { AuthProvider, useAuth } from '../../source/components/AuthProvider.js';
import { loadAuthToken } from '../../source/lib/auth.js';
import { describe, it, expect, vi, beforeEach } from 'vitest';
import { Text } from 'ink';
import delay from 'delay';

vi.mock('../../source/lib/auth.js', () => ({
loadAuthToken: vi.fn(),
}));

describe('AuthProvider', () => {
it('should display loading text while loading token', async () => {
(loadAuthToken as any).mockResolvedValueOnce(new Promise(() => {}));

const { lastFrame } = render(
<AuthProvider>
<Text>Child Component</Text>
</AuthProvider>,
);

expect(lastFrame()).toContain('Loading Token');
});
it('should display error message if loading token fails', async () => {
(loadAuthToken as any).mockRejectedValueOnce(
new Error('Failed to load token'),
);

const { lastFrame } = render(
<AuthProvider>
<Text>Child Component</Text>
</AuthProvider>,
);

await delay(50);
expect(lastFrame()).toContain('Failed to load token');
});

it('should display children when token is loaded successfully', async () => {
(loadAuthToken as any).mockResolvedValueOnce('mocked-token');

const { lastFrame } = render(
<AuthProvider>
<Text>Child Component</Text>
</AuthProvider>,
);

await delay(50);
expect(lastFrame()).toContain('Child Component');
});
it('should use the auth context successfully', async () => {
const ChildComponent = () => {
const { authToken } = useAuth();
return <Text>{authToken || 'No token'}</Text>;
};

(loadAuthToken as any).mockResolvedValueOnce('mocked-token');

const { lastFrame } = render(
<AuthProvider>
<ChildComponent />
</AuthProvider>,
);

await delay(100);
expect(lastFrame()).toContain('mocked-token');
});

it('should throw an error when useAuth is called outside of AuthProvider', () => {
const ChildComponent = () => {
let apiKey: string;
try {
const { authToken } = useAuth();
apiKey = authToken;
} catch (error) {
return <Text>useAuth must be used within an AuthProvider</Text>;
}
return <Text>{apiKey || 'No token'}</Text>;
};
const { lastFrame } = render(<ChildComponent />);
expect(lastFrame()).toContain(
'useAuth must be used within an AuthProvider',
);
});
});
37 changes: 37 additions & 0 deletions tests/components/PDPCommand.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import React from 'react';
import { describe, it, expect, vi } from 'vitest';
import { render } from 'ink-testing-library';
import PDPCommand from '../../source/components/PDPCommand';
import { AuthProvider } from '../../source/components/AuthProvider';
import delay from 'delay';
import { loadAuthToken } from '../../source/lib/auth';
vi.mock('../../source/lib/auth', () => ({
loadAuthToken: vi.fn(),
}));
describe('PDP Component', () => {
it('should render the PDP component with auth token', async () => {
(loadAuthToken as any).mockResolvedValueOnce(
'permit_key_'.concat('a'.repeat(97)),
);
const { lastFrame } = render(
<AuthProvider>
<PDPCommand opa={8181} />
</AuthProvider>,
);
expect(lastFrame()?.toString()).toMatch('Loading Token');
await delay(50);
expect(lastFrame()?.toString()).toMatch(
'Run the following command from your terminal:',
);
});
it('should render the Spinner', async () => {
const { lastFrame } = render(
<AuthProvider>
<PDPCommand opa={8181} />
</AuthProvider>,
);
expect(lastFrame()?.toString()).toMatch('Loading Token');
await delay(50);
expect(lastFrame()?.toString()).toMatch('Loading command');
});
});
63 changes: 63 additions & 0 deletions tests/github.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -384,5 +384,68 @@ describe('GiHub Complete Flow', () => {
await delay(50);
const frameString = lastFrame()?.toString() ?? '';
expect(frameString).toMatch(/GitOps Configuration Wizard - GitHub/);


await delay(50);
stdin.write(arrowDown);
await delay(50);
stdin.write(enter);
await delay(50);
expect(lastFrame()?.toString()).toMatch(/Enter Your RepositoryKey :/);
await delay(50);
stdin.write('repo3');
await delay(50);
stdin.write(enter);
await delay(50);
expect(lastFrame()?.toString()).toMatch(/SSH Key Generated./);
await delay(50);
stdin.write('[email protected]:user/repository.git');
await delay(50);
stdin.write(enter);
expect(lastFrame()?.toString()).toMatch(/Enter the Branch Name:/);
await delay(50);
stdin.write('main');
await delay(50);
stdin.write(enter);
await delay(50);
expect(lastFrame()?.toString()).toMatch(
'Invalid configuration. Please check the configuration and try again.',
);
});
it('should work with inactive argument', async () => {
const { stdin, lastFrame } = render(
<GitHub options={{ key: demoPermitKey, inactive: true }} />,
);
const frameString = lastFrame()?.toString() ?? '';
expect(frameString).toMatch(/Loading Token/);
await delay(100);
expect(lastFrame()?.toString()).toMatch(
/GitOps Configuration Wizard - GitHub/,
);
await delay(50);
stdin.write(arrowDown);
await delay(50);
stdin.write(enter);
await delay(50);
expect(lastFrame()?.toString()).toMatch(/Enter Your RepositoryKey :/);
await delay(50);
stdin.write('repo3');
await delay(50);
stdin.write(enter);
await delay(50);
expect(lastFrame()?.toString()).toMatch(/SSH Key Generated./);
await delay(50);
stdin.write('[email protected]:user/repository.git');
await delay(50);
stdin.write(enter);
expect(lastFrame()?.toString()).toMatch(/Enter the Branch Name:/);
await delay(50);
stdin.write('main');
await delay(50);
stdin.write(enter);
await delay(50);
expect(lastFrame()?.toString()).toMatch(
/Your GitOps is configured succesffuly. To complete the setup, remember to activate it later/,
);
});
});
Loading
Loading