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

Unit test getPersonById #1010

Merged
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
328 changes: 131 additions & 197 deletions src/store/__test__/main.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,38 +14,38 @@ import mockBounties, {
filterBounty
} from '../../bounties/__mock__/mockBounties.data';

let fetchStub: sinon.SinonStub;
let mockApiResponseData: any[];
describe('Main store', () => {
let fetchStub: sinon.SinonStub;
let mockApiResponseData: any[];

const origFetch = global.fetch;
const origFetch = global.fetch;

const Crypto = {
getRandomValues: (arr: Uint8Array) => {
for (let i = 0; i < arr.length; i++) {
arr[i] = Math.floor(Math.random() * 256);
const Crypto = {
getRandomValues: (arr: Uint8Array) => {
for (let i = 0; i < arr.length; i++) {
arr[i] = Math.floor(Math.random() * 256);
}
return arr;
}
return arr;
}
};

beforeAll(() => {
fetchStub = sinon.stub(global, 'fetch');
fetchStub.returns(Promise.resolve({ status: 200, json: () => Promise.resolve({}) })); // Mock a default behavior
mockApiResponseData = [
{ uuid: 'cm3eulatu2rvqi9o75ug' },
{ uuid: 'cldl1g04nncmf23du7kg' },
{ orgUUID: 'cmas9gatu2rvqiev4ur0' }
];
global.crypto = Crypto as any;
});
};

beforeAll(() => {
fetchStub = sinon.stub(global, 'fetch');
fetchStub.returns(Promise.resolve({ status: 200, json: () => Promise.resolve({}) })); // Mock a default behavior
mockApiResponseData = [
{ uuid: 'cm3eulatu2rvqi9o75ug' },
{ uuid: 'cldl1g04nncmf23du7kg' },
{ orgUUID: 'cmas9gatu2rvqiev4ur0' }
];
global.crypto = Crypto as any;
});

afterAll(() => {
global.fetch = origFetch;
afterAll(() => {
global.fetch = origFetch;

sinon.restore();
});
sinon.restore();
});

describe('Main store', () => {
beforeEach(async () => {
uiStore.setMeInfo(user);
localStorageMock.setItem('ui', JSON.stringify(uiStore));
Expand Down Expand Up @@ -1471,11 +1471,13 @@ describe('getUserRoles', () => {
const validUser = 'valid-user-456';
const mockJwt = 'test_jwt';
const mockSessionId = 'test-session-id';
let fetchStub: sinon.SinonStub;

beforeEach(() => {
mainStore = new MainStore();
uiStore.setMeInfo({ ...user, tribe_jwt: mockJwt });
sinon.stub(mainStore, 'getSessionId').returns(mockSessionId);
fetchStub = sinon.stub(window, 'fetch');
});

afterEach(() => {
Expand Down Expand Up @@ -1667,177 +1669,6 @@ describe('getUserRoles', () => {
expect(result).toEqual(mockRoles);
});
});

it('Special Characters in UUID/User', async () => {
const specialUuid = '!@#$%^&*()';
const specialUser = '你好世界';

fetchStub.resolves({
ok: true,
status: 200,
json: () => Promise.resolve([{ id: 1, name: 'admin' }])
} as Response);

const result = await mainStore.getUserRoles(specialUuid, specialUser);

waitFor(() => {
sinon.assert.calledWithMatch(
fetchStub,
`${TribesURL}/workspaces/users/role/${encodeURIComponent(specialUuid)}/${encodeURIComponent(
specialUser
)}`,
{
headers: {
'x-jwt': mockJwt,
'Content-Type': 'application/json',
'x-session-id': mockSessionId
}
}
);
expect(result).toHaveLength(1);
});
});

it('Invalid JWT Token', async () => {
uiStore.setMeInfo({ ...user, tribe_jwt: 'invalid_jwt' });

fetchStub.resolves({
ok: false,
status: 401,
json: () => Promise.resolve({ error: 'Invalid JWT' })
} as Response);

const result = await mainStore.getUserRoles(validUuid, validUser);
expect(result).toEqual([]);
});

it('Cross-Origin Request', async () => {
fetchStub.rejects(new Error('Cross-Origin Request Blocked'));

const result = await mainStore.getUserRoles(validUuid, validUser);
expect(result).toEqual([]);
expect(fetchStub.getCall(0).args[1].mode).toBe('cors');
});

it('Malformed UUID', async () => {
const malformedUuid = 'not-a-valid-uuid-format';

fetchStub.resolves({
ok: false,
status: 400,
json: () => Promise.resolve({ error: 'Malformed UUID' })
} as Response);

waitFor(() => {
const result = mainStore.getUserRoles(malformedUuid, validUser);
expect(result).toEqual([]);
});
});

it('Malformed User', async () => {
const malformedUser = '@invalid@user@';

fetchStub.resolves({
ok: false,
status: 400,
json: () => Promise.resolve({ error: 'Malformed User' })
} as Response);

const result = await mainStore.getUserRoles(validUuid, malformedUser);
expect(result).toEqual([]);
});

it('Expired Session ID', async () => {
fetchStub.resolves({
ok: false,
status: 401,
json: () => Promise.resolve({ error: 'Session expired' })
} as Response);

const result = await mainStore.getUserRoles(validUuid, validUser);
expect(result).toEqual([]);
});

it('Empty UUID with Valid User', async () => {
const result = await mainStore.getUserRoles('', validUser);
waitFor(() => {
expect(result).toEqual([]);
sinon.assert.calledWithMatch(
fetchStub,
sinon.match((url: string) => url.includes('//')),
sinon.match.any
);
});
});

it('Empty User with Valid UUID', async () => {
const result = await mainStore.getUserRoles(validUuid, '');
waitFor(() => {
expect(result).toEqual([]);
sinon.assert.calledWithMatch(
fetchStub,
sinon.match((url: string) => url.endsWith('/')),
sinon.match.any
);
});
});

it('Multiple Consecutive API Calls', async () => {
const mockRoles = [{ id: 1, name: 'admin' }];
fetchStub.resolves({
ok: true,
status: 200,
json: () => Promise.resolve(mockRoles)
} as Response);

const promises = Array(5)
.fill(null)
.map(() => mainStore.getUserRoles(validUuid, validUser));
waitFor(async () => {
const results = await Promise.all(promises);
results.forEach((result: any) => {
expect(result).toEqual(mockRoles);
});
expect(fetchStub.callCount).toBe(5);
});
});

it('Response with Empty Role Names', async () => {
const rolesWithEmptyNames = [
{ id: 1, name: '' },
{ id: 2, name: null },
{ id: 3, name: undefined }
];

fetchStub.resolves({
ok: true,
status: 200,
json: () => Promise.resolve(rolesWithEmptyNames)
} as Response);

waitFor(async () => {
const result = await mainStore.getUserRoles(validUuid, validUser);
expect(result).toEqual(rolesWithEmptyNames);
});
});

it('Response with Duplicate Role IDs', async () => {
const duplicateRoles = [
{ id: 1, name: 'admin' },
{ id: 1, name: 'super_admin' }
];

fetchStub.resolves({
ok: true,
status: 200,
json: () => Promise.resolve(duplicateRoles)
} as Response);

waitFor(async () => {
const result = await mainStore.getUserRoles(validUuid, validUser);
expect(result).toEqual(duplicateRoles);
});
});
});

describe('MainStore.setPersonBounties', () => {
Expand Down Expand Up @@ -2170,3 +2001,106 @@ describe('setPeople', () => {
expect(() => mainStore.setPeople([validInput[0], undefined])).toThrow(TypeError);
});
});

describe('getPersonById', () => {
let mainStore: MainStore;
const mockJwt = 'test_jwt';
const mockSessionId = 'test-session-id';
let fetchStub: sinon.SinonStub;

beforeEach(() => {
mainStore = new MainStore();
uiStore.setMeInfo({ ...user, tribe_jwt: mockJwt });
sinon.stub(mainStore, 'getSessionId').returns(mockSessionId);
fetchStub = sinon.stub(window, 'fetch');
});

afterEach(() => {
sinon.restore();
});

const tests = [
{
name: 'Valid ID Input',
id: 1,
mockResponse: { id: 1 },
expectedPerson: { id: 1 },
expectError: false
},
{
name: 'Another Valid ID Input',
id: 2,
mockResponse: { id: 2 },
expectedPerson: { id: 2 },
expectError: false
},
{
name: 'Minimum ID Value',
id: 0,
mockResponse: { id: 0 },
expectedPerson: { id: 0 },
expectError: false
},
{
name: 'Maximum ID Value',
id: 2147483647,
mockResponse: null,
mockError: new Error('not found'),
expectedPerson: null,
expectError: true
},
{
name: 'Non-Existent ID',
id: 9999,
mockResponse: null,
mockError: new Error('not found'),
expectedPerson: null,
expectError: true
},
{
name: 'Negative ID',
id: -1,
mockResponse: null,
mockError: new Error('invalid id'),
expectedPerson: null,
expectError: true
},
{
name: 'ID as a Floating Point Number',
id: 1.5,
mockResponse: { id: 1 },
expectedPerson: { id: 1 },
expectError: false
}
];

tests.forEach((tt: any) => {
it(tt.name, async () => {
if (tt.mockResponse) {
fetchStub.resolves({
ok: true,
status: 200,
json: () => Promise.resolve(tt.mockResponse)
} as Response);
} else {
fetchStub.rejects(tt.mockError || new Error('Unknown error'));
}

try {
const person = await mainStore.getPersonById(tt.id);

if (tt.expectError) {
fail('Expected an error but did not receive one');
} else {
expect(person).toEqual(tt.expectedPerson);
}
} catch (err) {
if (!tt.expectError) {
fail(`Did not expect an error but received: ${err}`);
} else {
expect(err).toEqual(tt.mockError);
}
}
});
});
});
15 changes: 13 additions & 2 deletions src/store/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2582,7 +2582,8 @@ export class MainStore {
try {
if (!uiStore.meInfo) return [];
const info = uiStore.meInfo;
const r: any = await fetch(`${TribesURL}/workspaces/users/role/${uuid}/${user}`, {

const r: Response = await fetch(`${TribesURL}/workspaces/users/role/${uuid}/${user}`, {
method: 'GET',
mode: 'cors',
headers: {
Expand All @@ -2592,7 +2593,17 @@ export class MainStore {
}
});

return r.json();
if (!r.ok) {
console.error(`Fetch failed with status: ${r.status}`);
return [];
}

try {
return await r.json();
} catch (jsonError) {
console.error('JSON Parsing Error:', jsonError);
return [];
}
} catch (e) {
console.log('Error getUserRoles', e);
return [];
Expand Down
Loading