Skip to content

Commit

Permalink
Merge pull request #1010 from MahtabBukhari/unit-test-for-get-person-…
Browse files Browse the repository at this point in the history
…by-id

Unit test getPersonById
  • Loading branch information
humansinstitute authored Feb 3, 2025
2 parents d9c3b7f + cae7c75 commit df910e5
Show file tree
Hide file tree
Showing 2 changed files with 144 additions and 199 deletions.
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 @@ -2330,3 +2161,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

0 comments on commit df910e5

Please sign in to comment.