Skip to content

Commit 35d7fe2

Browse files
committed
add some tests
1 parent d9c8602 commit 35d7fe2

File tree

8 files changed

+2978
-713
lines changed

8 files changed

+2978
-713
lines changed

web-app/package-lock.json

Lines changed: 2665 additions & 699 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

web-app/package.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"name": "vite-app ready",
2+
"name": "smartapi app",
33
"version": "0.0.0",
44
"private": true,
55
"scripts": {
@@ -51,7 +51,7 @@
5151
"@rushstack/eslint-patch": "^1.5.1",
5252
"@vitejs/plugin-vue": "^4.4.0",
5353
"@vue/eslint-config-prettier": "^8.0.0",
54-
"@vue/test-utils": "^2.4.1",
54+
"@vue/test-utils": "^2.4.6",
5555
"cypress": "^13.3.1",
5656
"eslint": "^8.51.0",
5757
"eslint-plugin-cypress": "^2.15.1",
@@ -60,6 +60,6 @@
6060
"prettier": "^3.0.3",
6161
"start-server-and-test": "^2.0.1",
6262
"vite": "^4.4.11",
63-
"vitest": "^0.34.6"
63+
"vitest": "^2.0.5"
6464
}
6565
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import { mount } from '@vue/test-utils';
2+
import { describe, it, expect, vi } from 'vitest';
3+
import CopyButton from '@/components/CopyButton.vue';
4+
5+
describe('CopyButton.vue', () => {
6+
it('renders slot content when not animating', () => {
7+
const wrapper = mount(CopyButton, {
8+
slots: {
9+
title: 'Click Me'
10+
}
11+
});
12+
expect(wrapper.text()).toContain('Click Me');
13+
});
14+
15+
it('renders "Copied!" when animating', async () => {
16+
const wrapper = mount(CopyButton, {
17+
slots: {
18+
title: 'Click Me'
19+
}
20+
});
21+
22+
await wrapper.vm.animate();
23+
await wrapper.vm.$nextTick();
24+
25+
expect(wrapper.text()).toContain('Copied!');
26+
});
27+
28+
it('has correct classes and attributes', () => {
29+
const wrapper = mount(CopyButton, {
30+
props: {
31+
copy: 'Sample text'
32+
}
33+
});
34+
35+
const button = wrapper.find('button');
36+
37+
expect(button.attributes('data-clipboard-text')).toBe('Sample text');
38+
expect(button.classes()).toContain('CopyButton');
39+
expect(button.classes()).toContain('copyBtn');
40+
expect(button.classes()).toContain(`cp${wrapper.vm.badgeID}`);
41+
});
42+
});
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
import { mount } from '@vue/test-utils';
2+
import { describe, it, expect } from 'vitest';
3+
import EntityPill from '@/components/EntityPill.vue';
4+
5+
const mockStore = {
6+
getters: {
7+
getEntityColor: (object) => {
8+
// Mock color logic for the object
9+
return object === 'Entity' ? '#FF0000' : '#00FF00';
10+
}
11+
}
12+
};
13+
14+
describe('EntityPill.vue', () => {
15+
it('renders the correct object text', () => {
16+
const wrapper = mount(EntityPill, {
17+
props: {
18+
object: 'Entity',
19+
subjects: []
20+
},
21+
global: {
22+
mocks: {
23+
$store: mockStore
24+
}
25+
}
26+
});
27+
28+
expect(wrapper.text()).toContain('Entity');
29+
});
30+
31+
it('renders subjects correctly and handles "See More/Less" functionality', async () => {
32+
const subjects = ['Subject 1', 'Subject 2', 'Subject 3', 'Subject 4', 'Subject 5', 'Subject 6', 'Subject 7', 'Subject 8'];
33+
34+
const wrapper = mount(EntityPill, {
35+
props: {
36+
object: 'Entity',
37+
subjects
38+
},
39+
global: {
40+
mocks: {
41+
$store: mockStore
42+
}
43+
}
44+
});
45+
46+
// Check if only limited subjects are rendered initially
47+
const listItems = wrapper.findAll('li');
48+
expect(listItems).toHaveLength(8);
49+
50+
// Check if the "See More" button is displayed correctly
51+
const seeMoreButton = wrapper.find('.blue-text.pointer');
52+
expect(seeMoreButton.exists()).toBe(true);
53+
expect(seeMoreButton.text()).toContain('See More (8)');
54+
55+
// Simulate clicking "See More"
56+
await seeMoreButton.trigger('click');
57+
58+
// Check if all subjects are rendered after clicking "See More"
59+
expect(wrapper.findAll('li')).toHaveLength(9);
60+
expect(seeMoreButton.text()).toContain('See Less');
61+
});
62+
});

web-app/src/__tests__/HelloWorld.spec.js

Lines changed: 0 additions & 11 deletions
This file was deleted.
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
import { shallowMount } from '@vue/test-utils';
2+
import { describe, it, expect, beforeEach } from 'vitest';
3+
import RegistryItem from '@/components/RegistryItem.vue';
4+
5+
describe('RegistryItem.vue', () => {
6+
let wrapper;
7+
const apiMock = {
8+
info: { title: 'Test API', version: '1.0', description: 'API Description' },
9+
_status: { uptime_status: 'OK', uptime_msg: 'All good' },
10+
_meta: { username: 'testUser', has_metakg: true, last_updated: '2024-09-01', url: 'http://api.com' },
11+
paths: {
12+
'/example': {
13+
get: { summary: 'Get example' }
14+
}
15+
},
16+
tags: [{ name: 'tag1' }, { name: 'tag2' }],
17+
openapi: '3.0.1'
18+
};
19+
const userMock = { login: 'testUser' };
20+
const mockRoute = {
21+
path: '/test-route',
22+
query: {
23+
tags: 'example-tag'
24+
}
25+
};
26+
27+
beforeEach(() => {
28+
wrapper = shallowMount(RegistryItem, {
29+
propsData: { api: apiMock, user: userMock },
30+
mocks: {
31+
$route: mockRoute
32+
}
33+
});
34+
});
35+
36+
it('renders the API title and version correctly', () => {
37+
const title = wrapper.find('.card-title span.blue-grey-text');
38+
const version = wrapper.find('.card-title small.grey-text');
39+
expect(title.text()).toBe('Test API');
40+
expect(version.text()).toBe('1.0');
41+
});
42+
43+
it('shows the correct badges based on the API version', () => {
44+
const oasBadge = wrapper.find('.versionBadge.green');
45+
expect(oasBadge.exists()).toBe(true);
46+
expect(oasBadge.text()).toContain('OAS3');
47+
});
48+
49+
it('renders the API operations', () => {
50+
const operations = wrapper.findAll('tbody tr');
51+
expect(operations.length).toBe(1); // Only 1 operation is defined
52+
expect(operations.at(0).text()).toContain('GET');
53+
expect(operations.at(0).text()).toContain('/example');
54+
});
55+
56+
it('toggles the details view when clicking the Details button', async () => {
57+
const detailsButton = wrapper.find('button.indigo');
58+
await detailsButton.trigger('click');
59+
const detailsContent = wrapper.find('.detailsBack');
60+
expect(detailsContent.exists()).toBe(true); // Details should be shown
61+
});
62+
63+
it('renders the MetaKG button and toggles view', async () => {
64+
const metakgButton = wrapper.find('button.purple');
65+
expect(metakgButton.exists()).toBe(true); // MetaKG button should be visible
66+
await metakgButton.trigger('click');
67+
const metakgView = wrapper.findComponent({ name: 'RegistryMetaKG' });
68+
expect(metakgView.exists()).toBe(true); // MetaKG view should be rendered
69+
});
70+
});
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
import { describe, it, expect } from 'vitest';
2+
3+
import { mount } from '@vue/test-utils';
4+
import SourceStatus from '@/components/SourceStatus.vue';
5+
import UptimeStatus from '@/components/UptimeStatus.vue';
6+
7+
describe('SourceStatus Component', () => {
8+
const statuses = [
9+
{ status: 200, text: 'OK', clss: 'green' },
10+
{ status: 299, text: 'OK', clss: 'green' },
11+
{ status: 499, text: 'INVALID', clss: 'red' },
12+
{ status: 599, text: 'BROKEN', clss: 'purple' },
13+
{ status: 404, text: 'NOT FOUND', clss: 'orange' },
14+
{ status: undefined, text: 'N/A', clss: 'grey darken-1' },
15+
{ status: 123, text: '123', clss: 'black' },
16+
];
17+
18+
statuses.forEach(v => {
19+
it(`renders proper URL monitor status for status ${v.status}`, () => {
20+
const wrapper = mount(SourceStatus, { props: { refresh_status: v.status } });
21+
const statusElement = wrapper.find('.white-text.center-align');
22+
23+
setTimeout(() => {
24+
expect(statusElement.text()).toBe(v.text);
25+
expect(statusElement.classes()).toContain(v.clss);
26+
}, 200);
27+
});
28+
});
29+
});
30+
31+
describe('UptimeStatus Component', () => {
32+
const statuses = [
33+
{ uptime_status: 'unknown', text: 'UNKNOWN', clss: 'orange' },
34+
{ uptime_status: 'pass', text: 'PASS', clss: 'green' },
35+
{ uptime_status: 'fail', text: 'FAIL', clss: 'red' },
36+
{ uptime_status: 'incompatible', text: 'INCOMPATIBLE', clss: 'blue' },
37+
{ uptime_status: undefined, text: 'N/A', clss: 'grey' },
38+
{ uptime_status: 'other', text: 'N/A', clss: 'grey' }
39+
];
40+
41+
statuses.forEach(v => {
42+
it(`renders proper uptime status for status ${v.uptime_status}`, () => {
43+
const wrapper = mount(UptimeStatus, { props: { uptime_status: v.uptime_status } });
44+
const statusElement = wrapper.find('.white-text.center-align');
45+
46+
setTimeout(() => {
47+
expect(statusElement.text()).toBe(v.text);
48+
expect(statusElement.classes()).toContain(v.clss);
49+
}, 200);
50+
});
51+
});
52+
});
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
// import { describe, expect, vi } from 'vitest';
2+
// import { mount } from '@vue/test-utils';
3+
// import { createRouter, createWebHistory } from 'vue-router';
4+
// import App from '@/App.vue';
5+
// import Egg from '@/components/Icons/Egg.vue';
6+
// import { routes } from '../router/routes'
7+
// import { createStore } from 'vuex';
8+
9+
// const router = createRouter({
10+
// history: createWebHistory(),
11+
// routes
12+
// });
13+
14+
// const actions = {
15+
// loadTagFilters: vi.fn(),
16+
// loadOwnerFilters: vi.fn(),
17+
// loadTranslatorFilters: vi.fn(),
18+
// };
19+
20+
// const store = createStore({
21+
// actions,
22+
// });
23+
24+
// // Mock SweetAlert2
25+
// const mockSwal = vi.fn();
26+
27+
// describe('renders component part of Home component via routing', async () => {
28+
// router.push('/');
29+
// await router.isReady();
30+
31+
// // Create a mock element and append it to the document body
32+
// const cookieButton = document.createElement('button');
33+
// cookieButton.id = 'cookieButton';
34+
// document.body.appendChild(cookieButton);
35+
36+
// // Create a mock element and append it to the document body
37+
// const yearSpan = document.createElement('span');
38+
// yearSpan.id = 'year';
39+
// document.body.appendChild(yearSpan);
40+
41+
// const wrapper = mount(App, {
42+
// global: {
43+
// plugins: [router, store],
44+
// mocks: {
45+
// '$swal': mockSwal,
46+
// },
47+
// }
48+
// });
49+
50+
// expect(wrapper.findComponent(Egg).exists()).toBe(true);
51+
// });
52+
53+
// // describe('renders component part of ABOUT view via routing', async () => {
54+
// // router.push('/about');
55+
// // await router.isReady();
56+
57+
// // // Create a mock element and append it to the document body
58+
// // const yearSpan = document.createElement('span');
59+
// // yearSpan.id = 'year';
60+
// // document.body.appendChild(yearSpan);
61+
62+
// // const wrapper = mount(App, {
63+
// // global: {
64+
// // plugins: [router, store]
65+
// // }
66+
// // });
67+
68+
// // setTimeout(() => {
69+
// // expect(wrapper).toContain("BUILDING A CONNECTED NETWORK OF FAIR APIS");
70+
// // }, 200);
71+
// // });
72+
73+
// // describe('renders About component via routing', async () => {
74+
// // router.push('/about');
75+
// // await router.isReady();
76+
77+
// // const wrapper = mount(App, {
78+
// // global: {
79+
// // plugins: [router]
80+
// // }
81+
// // });
82+
83+
// // expect(wrapper.findComponent(About).exists()).toBe(true);
84+
// // });

0 commit comments

Comments
 (0)