Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'spec/frontend/observability')
-rw-r--r--spec/frontend/observability/client_spec.js233
-rw-r--r--spec/frontend/observability/index_spec.js64
-rw-r--r--spec/frontend/observability/observability_app_spec.js201
-rw-r--r--spec/frontend/observability/observability_container_spec.js6
-rw-r--r--spec/frontend/observability/skeleton_spec.js86
5 files changed, 213 insertions, 377 deletions
diff --git a/spec/frontend/observability/client_spec.js b/spec/frontend/observability/client_spec.js
index 056175eac07..68a53131539 100644
--- a/spec/frontend/observability/client_spec.js
+++ b/spec/frontend/observability/client_spec.js
@@ -12,7 +12,8 @@ describe('buildClient', () => {
const tracingUrl = 'https://example.com/tracing';
const provisioningUrl = 'https://example.com/provisioning';
-
+ const servicesUrl = 'https://example.com/services';
+ const operationsUrl = 'https://example.com/services/$SERVICE_NAME$/operations';
const FETCHING_TRACES_ERROR = 'traces are missing/invalid in the response';
beforeEach(() => {
@@ -22,6 +23,8 @@ describe('buildClient', () => {
client = buildClient({
tracingUrl,
provisioningUrl,
+ servicesUrl,
+ operationsUrl,
});
});
@@ -29,6 +32,27 @@ describe('buildClient', () => {
axiosMock.restore();
});
+ describe('buildClient', () => {
+ it('rejects if params are missing', () => {
+ const e = new Error(
+ 'missing required params. provisioningUrl, tracingUrl, servicesUrl, operationsUrl are required',
+ );
+ expect(() =>
+ buildClient({ tracingUrl: 'test', servicesUrl: 'test', operationsUrl: 'test' }),
+ ).toThrow(e);
+ expect(() =>
+ buildClient({ provisioningUrl: 'test', servicesUrl: 'test', operationsUrl: 'test' }),
+ ).toThrow(e);
+ expect(() =>
+ buildClient({ provisioningUrl: 'test', tracingUrl: 'test', operationsUrl: 'test' }),
+ ).toThrow(e);
+ expect(() =>
+ buildClient({ provisioningUrl: 'test', tracingUrl: 'test', servicesUrl: 'test' }),
+ ).toThrow(e);
+ expect(() => buildClient({})).toThrow(e);
+ });
+ });
+
describe('isTracingEnabled', () => {
it('returns true if requests succeedes', async () => {
axiosMock.onGet(provisioningUrl).reply(200, {
@@ -145,18 +169,18 @@ describe('buildClient', () => {
describe('fetchTraces', () => {
it('fetches traces from the tracing URL', async () => {
- const mockTraces = [
- {
- trace_id: 'trace-1',
- duration_nano: 3000,
- spans: [{ duration_nano: 1000 }, { duration_nano: 2000 }],
- },
- { trace_id: 'trace-2', duration_nano: 3000, spans: [{ duration_nano: 2000 }] },
- ];
-
- axiosMock.onGet(tracingUrl).reply(200, {
- traces: mockTraces,
- });
+ const mockResponse = {
+ traces: [
+ {
+ trace_id: 'trace-1',
+ duration_nano: 3000,
+ spans: [{ duration_nano: 1000 }, { duration_nano: 2000 }],
+ },
+ { trace_id: 'trace-2', duration_nano: 3000, spans: [{ duration_nano: 2000 }] },
+ ],
+ };
+
+ axiosMock.onGet(tracingUrl).reply(200, mockResponse);
const result = await client.fetchTraces();
@@ -165,7 +189,7 @@ describe('buildClient', () => {
withCredentials: true,
params: new URLSearchParams(),
});
- expect(result).toEqual(mockTraces);
+ expect(result).toEqual(mockResponse);
});
it('rejects if traces are missing', async () => {
@@ -197,28 +221,42 @@ describe('buildClient', () => {
expect(getQueryParam()).toBe('');
});
+ it('appends page_token if specified', async () => {
+ await client.fetchTraces({ pageToken: 'page-token' });
+
+ expect(getQueryParam()).toBe('page_token=page-token');
+ });
+
+ it('appends page_size if specified', async () => {
+ await client.fetchTraces({ pageSize: 10 });
+
+ expect(getQueryParam()).toBe('page_size=10');
+ });
+
it('converts filter to proper query params', async () => {
await client.fetchTraces({
- durationMs: [
- { operator: '>', value: '100' },
- { operator: '<', value: '1000' },
- ],
- operation: [
- { operator: '=', value: 'op' },
- { operator: '!=', value: 'not-op' },
- ],
- serviceName: [
- { operator: '=', value: 'service' },
- { operator: '!=', value: 'not-service' },
- ],
- period: [{ operator: '=', value: '5m' }],
- traceId: [
- { operator: '=', value: 'trace-id' },
- { operator: '!=', value: 'not-trace-id' },
- ],
+ filters: {
+ durationMs: [
+ { operator: '>', value: '100' },
+ { operator: '<', value: '1000' },
+ ],
+ operation: [
+ { operator: '=', value: 'op' },
+ { operator: '!=', value: 'not-op' },
+ ],
+ serviceName: [
+ { operator: '=', value: 'service' },
+ { operator: '!=', value: 'not-service' },
+ ],
+ period: [{ operator: '=', value: '5m' }],
+ traceId: [
+ { operator: '=', value: 'trace-id' },
+ { operator: '!=', value: 'not-trace-id' },
+ ],
+ },
});
expect(getQueryParam()).toBe(
- 'gt[duration_nano]=100000&lt[duration_nano]=1000000' +
+ 'gt[duration_nano]=100000000&lt[duration_nano]=1000000000' +
'&operation=op&not[operation]=not-op' +
'&service_name=service&not[service_name]=not-service' +
'&period=5m' +
@@ -228,17 +266,21 @@ describe('buildClient', () => {
it('handles repeated params', async () => {
await client.fetchTraces({
- operation: [
- { operator: '=', value: 'op' },
- { operator: '=', value: 'op2' },
- ],
+ filters: {
+ operation: [
+ { operator: '=', value: 'op' },
+ { operator: '=', value: 'op2' },
+ ],
+ },
});
expect(getQueryParam()).toBe('operation=op&operation=op2');
});
it('ignores unsupported filters', async () => {
await client.fetchTraces({
- unsupportedFilter: [{ operator: '=', value: 'foo' }],
+ filters: {
+ unsupportedFilter: [{ operator: '=', value: 'foo' }],
+ },
});
expect(getQueryParam()).toBe('');
@@ -246,8 +288,10 @@ describe('buildClient', () => {
it('ignores empty filters', async () => {
await client.fetchTraces({
- durationMs: null,
- traceId: undefined,
+ filters: {
+ durationMs: null,
+ traceId: undefined,
+ },
});
expect(getQueryParam()).toBe('');
@@ -255,28 +299,103 @@ describe('buildClient', () => {
it('ignores unsupported operators', async () => {
await client.fetchTraces({
- durationMs: [
- { operator: '*', value: 'foo' },
- { operator: '=', value: 'foo' },
- { operator: '!=', value: 'foo' },
- ],
- operation: [
- { operator: '>', value: 'foo' },
- { operator: '<', value: 'foo' },
- ],
- serviceName: [
- { operator: '>', value: 'foo' },
- { operator: '<', value: 'foo' },
- ],
- period: [{ operator: '!=', value: 'foo' }],
- traceId: [
- { operator: '>', value: 'foo' },
- { operator: '<', value: 'foo' },
- ],
+ filters: {
+ durationMs: [
+ { operator: '*', value: 'foo' },
+ { operator: '=', value: 'foo' },
+ { operator: '!=', value: 'foo' },
+ ],
+ operation: [
+ { operator: '>', value: 'foo' },
+ { operator: '<', value: 'foo' },
+ ],
+ serviceName: [
+ { operator: '>', value: 'foo' },
+ { operator: '<', value: 'foo' },
+ ],
+ period: [{ operator: '!=', value: 'foo' }],
+ traceId: [
+ { operator: '>', value: 'foo' },
+ { operator: '<', value: 'foo' },
+ ],
+ },
});
expect(getQueryParam()).toBe('');
});
});
});
+
+ describe('fetchServices', () => {
+ it('fetches services from the services URL', async () => {
+ const mockResponse = {
+ services: [{ name: 'service-1' }, { name: 'service-2' }],
+ };
+
+ axiosMock.onGet(servicesUrl).reply(200, mockResponse);
+
+ const result = await client.fetchServices();
+
+ expect(axios.get).toHaveBeenCalledTimes(1);
+ expect(axios.get).toHaveBeenCalledWith(servicesUrl, {
+ withCredentials: true,
+ });
+ expect(result).toEqual(mockResponse.services);
+ });
+
+ it('rejects if services are missing', async () => {
+ axiosMock.onGet(servicesUrl).reply(200, {});
+
+ const e = 'failed to fetch services. invalid response';
+ await expect(client.fetchServices()).rejects.toThrow(e);
+ expect(Sentry.captureException).toHaveBeenCalledWith(new Error(e));
+ });
+ });
+
+ describe('fetchOperations', () => {
+ const serviceName = 'test-service';
+ const parsedOperationsUrl = `https://example.com/services/${serviceName}/operations`;
+
+ it('fetches operations from the operations URL', async () => {
+ const mockResponse = {
+ operations: [{ name: 'operation-1' }, { name: 'operation-2' }],
+ };
+
+ axiosMock.onGet(parsedOperationsUrl).reply(200, mockResponse);
+
+ const result = await client.fetchOperations(serviceName);
+
+ expect(axios.get).toHaveBeenCalledTimes(1);
+ expect(axios.get).toHaveBeenCalledWith(parsedOperationsUrl, {
+ withCredentials: true,
+ });
+ expect(result).toEqual(mockResponse.operations);
+ });
+
+ it('rejects if serviceName is missing', async () => {
+ const e = 'fetchOperations() - serviceName is required.';
+ await expect(client.fetchOperations()).rejects.toThrow(e);
+ expect(Sentry.captureException).toHaveBeenCalledWith(new Error(e));
+ });
+
+ it('rejects if operationUrl does not contain $SERVICE_NAME$', async () => {
+ client = buildClient({
+ tracingUrl,
+ provisioningUrl,
+ servicesUrl,
+ operationsUrl: 'something',
+ });
+ const e = 'fetchOperations() - operationsUrl must contain $SERVICE_NAME$';
+ await expect(client.fetchOperations(serviceName)).rejects.toThrow(e);
+ expect(Sentry.captureException).toHaveBeenCalledWith(new Error(e));
+ });
+
+ it('rejects if operations are missing', async () => {
+ axiosMock.onGet(parsedOperationsUrl).reply(200, {});
+
+ const e = 'failed to fetch operations. invalid response';
+ await expect(client.fetchOperations(serviceName)).rejects.toThrow(e);
+ expect(Sentry.captureException).toHaveBeenCalledWith(new Error(e));
+ });
+ });
});
diff --git a/spec/frontend/observability/index_spec.js b/spec/frontend/observability/index_spec.js
deleted file mode 100644
index 25eb048c62b..00000000000
--- a/spec/frontend/observability/index_spec.js
+++ /dev/null
@@ -1,64 +0,0 @@
-import { createWrapper } from '@vue/test-utils';
-import Vue, { nextTick } from 'vue';
-import renderObservability from '~/observability/index';
-import ObservabilityApp from '~/observability/components/observability_app.vue';
-import { SKELETON_VARIANTS_BY_ROUTE } from '~/observability/constants';
-
-describe('renderObservability', () => {
- let element;
- let vueInstance;
- let component;
-
- const OBSERVABILITY_ROUTES = Object.keys(SKELETON_VARIANTS_BY_ROUTE);
- const SKELETON_VARIANTS = Object.values(SKELETON_VARIANTS_BY_ROUTE);
-
- beforeEach(() => {
- element = document.createElement('div');
- element.setAttribute('id', 'js-observability-app');
- element.dataset.observabilityIframeSrc = 'https://observe.gitlab.com/';
- document.body.appendChild(element);
-
- vueInstance = renderObservability();
- component = createWrapper(vueInstance).findComponent(ObservabilityApp);
- });
-
- afterEach(() => {
- element.remove();
- });
-
- it('should return a Vue instance', () => {
- expect(vueInstance).toEqual(expect.any(Vue));
- });
-
- it('should render the ObservabilityApp component', () => {
- expect(component.props('observabilityIframeSrc')).toBe('https://observe.gitlab.com/');
- });
-
- describe('skeleton variant', () => {
- it.each`
- pathDescription | path | variant
- ${'dashboards'} | ${OBSERVABILITY_ROUTES[0]} | ${SKELETON_VARIANTS[0]}
- ${'explore'} | ${OBSERVABILITY_ROUTES[1]} | ${SKELETON_VARIANTS[1]}
- ${'manage dashboards'} | ${OBSERVABILITY_ROUTES[2]} | ${SKELETON_VARIANTS[2]}
- ${'any other'} | ${'unknown/route'} | ${SKELETON_VARIANTS[0]}
- `(
- 'renders the $variant skeleton variant for $pathDescription path',
- async ({ path, variant }) => {
- component.vm.$router.push(path);
- await nextTick();
-
- expect(component.props('skeletonVariant')).toBe(variant);
- },
- );
- });
-
- it('handle route-update events', () => {
- component.vm.$router.push('/something?foo=bar');
- component.vm.$emit('route-update', { url: '/some_path' });
- expect(component.vm.$router.currentRoute.path).toBe('/something');
- expect(component.vm.$router.currentRoute.query).toEqual({
- foo: 'bar',
- observability_path: '/some_path',
- });
- });
-});
diff --git a/spec/frontend/observability/observability_app_spec.js b/spec/frontend/observability/observability_app_spec.js
deleted file mode 100644
index 392992a5962..00000000000
--- a/spec/frontend/observability/observability_app_spec.js
+++ /dev/null
@@ -1,201 +0,0 @@
-import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
-import { stubComponent } from 'helpers/stub_component';
-import ObservabilityApp from '~/observability/components/observability_app.vue';
-import ObservabilitySkeleton from '~/observability/components/skeleton/index.vue';
-import {
- MESSAGE_EVENT_TYPE,
- INLINE_EMBED_DIMENSIONS,
- FULL_APP_DIMENSIONS,
- SKELETON_VARIANT_EMBED,
-} from '~/observability/constants';
-
-import { darkModeEnabled } from '~/lib/utils/color_utils';
-
-jest.mock('~/lib/utils/color_utils');
-
-describe('ObservabilityApp', () => {
- let wrapper;
-
- const $route = {
- pathname: 'https://gitlab.com/gitlab-org/',
- path: 'https://gitlab.com/gitlab-org/-/observability/dashboards',
- query: { otherQuery: 100 },
- };
-
- const mockSkeletonOnContentLoaded = jest.fn();
-
- const findIframe = () => wrapper.findByTestId('observability-ui-iframe');
-
- const TEST_IFRAME_SRC = 'https://observe.gitlab.com/9970/?groupId=14485840';
-
- const TEST_USERNAME = 'test-user';
-
- const mountComponent = (props) => {
- wrapper = shallowMountExtended(ObservabilityApp, {
- propsData: {
- observabilityIframeSrc: TEST_IFRAME_SRC,
- ...props,
- },
- stubs: {
- ObservabilitySkeleton: stubComponent(ObservabilitySkeleton, {
- methods: { onContentLoaded: mockSkeletonOnContentLoaded },
- }),
- },
- mocks: {
- $route,
- },
- });
- };
-
- const dispatchMessageEvent = (message) =>
- window.dispatchEvent(new MessageEvent('message', message));
-
- beforeEach(() => {
- gon.current_username = TEST_USERNAME;
- });
-
- describe('iframe src', () => {
- it('should render an iframe with observabilityIframeSrc, decorated with light theme and username', () => {
- darkModeEnabled.mockReturnValueOnce(false);
- mountComponent();
- const iframe = findIframe();
-
- expect(iframe.exists()).toBe(true);
- expect(iframe.attributes('src')).toBe(
- `${TEST_IFRAME_SRC}&theme=light&username=${TEST_USERNAME}`,
- );
- });
-
- it('should render an iframe with observabilityIframeSrc decorated with dark theme and username', () => {
- darkModeEnabled.mockReturnValueOnce(true);
- mountComponent();
- const iframe = findIframe();
-
- expect(iframe.exists()).toBe(true);
- expect(iframe.attributes('src')).toBe(
- `${TEST_IFRAME_SRC}&theme=dark&username=${TEST_USERNAME}`,
- );
- });
- });
-
- describe('iframe sandbox', () => {
- it('should render an iframe with sandbox attributes', () => {
- mountComponent();
- const iframe = findIframe();
-
- expect(iframe.exists()).toBe(true);
- expect(iframe.attributes('sandbox')).toBe('allow-same-origin allow-forms allow-scripts');
- });
- });
-
- describe('iframe kiosk query param', () => {
- it('when inlineEmbed, it should set the proper kiosk query parameter', () => {
- mountComponent({
- inlineEmbed: true,
- });
-
- const iframe = findIframe();
-
- expect(iframe.attributes('src')).toBe(
- `${TEST_IFRAME_SRC}&theme=light&username=${TEST_USERNAME}&kiosk=inline-embed`,
- );
- });
- });
-
- describe('iframe size', () => {
- it('should set the specified size', () => {
- mountComponent({
- height: INLINE_EMBED_DIMENSIONS.HEIGHT,
- width: INLINE_EMBED_DIMENSIONS.WIDTH,
- });
-
- const iframe = findIframe();
-
- expect(iframe.attributes('width')).toBe(INLINE_EMBED_DIMENSIONS.WIDTH);
- expect(iframe.attributes('height')).toBe(INLINE_EMBED_DIMENSIONS.HEIGHT);
- });
-
- it('should fallback to default size', () => {
- mountComponent({});
-
- const iframe = findIframe();
-
- expect(iframe.attributes('width')).toBe(FULL_APP_DIMENSIONS.WIDTH);
- expect(iframe.attributes('height')).toBe(FULL_APP_DIMENSIONS.HEIGHT);
- });
- });
-
- describe('skeleton variant', () => {
- it('sets the specified skeleton variant', () => {
- mountComponent({ skeletonVariant: SKELETON_VARIANT_EMBED });
- const props = wrapper.findComponent(ObservabilitySkeleton).props();
-
- expect(props.variant).toBe(SKELETON_VARIANT_EMBED);
- });
-
- it('should have a default skeleton variant', () => {
- mountComponent();
- const props = wrapper.findComponent(ObservabilitySkeleton).props();
-
- expect(props.variant).toBe('dashboards');
- });
- });
-
- describe('on GOUI_ROUTE_UPDATE', () => {
- it('should emit a route-update event', () => {
- mountComponent();
-
- const payload = { url: '/explore' };
- dispatchMessageEvent({
- data: { type: MESSAGE_EVENT_TYPE.GOUI_ROUTE_UPDATE, payload },
- origin: 'https://observe.gitlab.com',
- });
-
- expect(wrapper.emitted('route-update')[0]).toEqual([payload]);
- });
- });
-
- describe('on GOUI_LOADED', () => {
- beforeEach(() => {
- mountComponent();
- });
-
- it('should call onContentLoaded method', () => {
- dispatchMessageEvent({
- data: { type: MESSAGE_EVENT_TYPE.GOUI_LOADED },
- origin: 'https://observe.gitlab.com',
- });
- expect(mockSkeletonOnContentLoaded).toHaveBeenCalled();
- });
-
- it('should not call onContentLoaded method if origin is different', () => {
- dispatchMessageEvent({
- data: { type: MESSAGE_EVENT_TYPE.GOUI_LOADED },
- origin: 'https://example.com',
- });
- expect(mockSkeletonOnContentLoaded).not.toHaveBeenCalled();
- });
-
- it('should not call onContentLoaded method if event type is different', () => {
- dispatchMessageEvent({
- data: { type: 'UNKNOWN_EVENT' },
- origin: 'https://observe.gitlab.com',
- });
- expect(mockSkeletonOnContentLoaded).not.toHaveBeenCalled();
- });
- });
-
- describe('on unmount', () => {
- it('should not emit any even on route update', () => {
- mountComponent();
- wrapper.destroy();
-
- dispatchMessageEvent({
- data: { type: MESSAGE_EVENT_TYPE.GOUI_ROUTE_UPDATE, payload: { url: '/explore' } },
- origin: 'https://observe.gitlab.com',
- });
-
- expect(wrapper.emitted('route-update')).toBeUndefined();
- });
- });
-});
diff --git a/spec/frontend/observability/observability_container_spec.js b/spec/frontend/observability/observability_container_spec.js
index 1152df072d4..5d838756308 100644
--- a/spec/frontend/observability/observability_container_spec.js
+++ b/spec/frontend/observability/observability_container_spec.js
@@ -16,6 +16,8 @@ describe('ObservabilityContainer', () => {
const OAUTH_URL = 'https://example.com/oauth';
const TRACING_URL = 'https://example.com/tracing';
const PROVISIONING_URL = 'https://example.com/provisioning';
+ const SERVICES_URL = 'https://example.com/services';
+ const OPERATIONS_URL = 'https://example.com/operations';
beforeEach(() => {
jest.spyOn(console, 'error').mockImplementation();
@@ -27,6 +29,8 @@ describe('ObservabilityContainer', () => {
oauthUrl: OAUTH_URL,
tracingUrl: TRACING_URL,
provisioningUrl: PROVISIONING_URL,
+ servicesUrl: SERVICES_URL,
+ operationsUrl: OPERATIONS_URL,
},
stubs: {
ObservabilitySkeleton: stubComponent(ObservabilitySkeleton, {
@@ -93,6 +97,8 @@ describe('ObservabilityContainer', () => {
expect(buildClient).toHaveBeenCalledWith({
provisioningUrl: PROVISIONING_URL,
tracingUrl: TRACING_URL,
+ servicesUrl: SERVICES_URL,
+ operationsUrl: OPERATIONS_URL,
});
expect(findIframe().exists()).toBe(false);
});
diff --git a/spec/frontend/observability/skeleton_spec.js b/spec/frontend/observability/skeleton_spec.js
index 979070cfb12..5501fa117e0 100644
--- a/spec/frontend/observability/skeleton_spec.js
+++ b/spec/frontend/observability/skeleton_spec.js
@@ -3,32 +3,16 @@ import { GlSkeletonLoader, GlAlert, GlLoadingIcon } from '@gitlab/ui';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import Skeleton from '~/observability/components/skeleton/index.vue';
-import DashboardsSkeleton from '~/observability/components/skeleton/dashboards.vue';
-import ExploreSkeleton from '~/observability/components/skeleton/explore.vue';
-import ManageSkeleton from '~/observability/components/skeleton/manage.vue';
-import EmbedSkeleton from '~/observability/components/skeleton/embed.vue';
-import {
- SKELETON_VARIANTS_BY_ROUTE,
- DEFAULT_TIMERS,
- SKELETON_VARIANT_EMBED,
-} from '~/observability/constants';
+import { DEFAULT_TIMERS } from '~/observability/constants';
describe('Skeleton component', () => {
let wrapper;
- const SKELETON_VARIANTS = [...Object.values(SKELETON_VARIANTS_BY_ROUTE), 'spinner'];
+ const findSpinner = () => wrapper.findComponent(GlLoadingIcon);
const findContentWrapper = () => wrapper.findByTestId('content-wrapper');
- const findExploreSkeleton = () => wrapper.findComponent(ExploreSkeleton);
-
- const findDashboardsSkeleton = () => wrapper.findComponent(DashboardsSkeleton);
-
- const findManageSkeleton = () => wrapper.findComponent(ManageSkeleton);
-
- const findEmbedSkeleton = () => wrapper.findComponent(EmbedSkeleton);
-
const findAlert = () => wrapper.findComponent(GlAlert);
const mountComponent = ({ ...props } = {}) => {
@@ -39,39 +23,39 @@ describe('Skeleton component', () => {
describe('on mount', () => {
beforeEach(() => {
- mountComponent({ variant: 'explore' });
+ mountComponent({ variant: 'spinner' });
});
describe('showing content', () => {
it('shows the skeleton if content is not loaded within CONTENT_WAIT_MS', async () => {
- expect(findExploreSkeleton().exists()).toBe(false);
- expect(findContentWrapper().isVisible()).toBe(false);
+ expect(findSpinner().exists()).toBe(false);
+ expect(findContentWrapper().exists()).toBe(false);
jest.advanceTimersByTime(DEFAULT_TIMERS.CONTENT_WAIT_MS);
await nextTick();
- expect(findExploreSkeleton().exists()).toBe(true);
- expect(findContentWrapper().isVisible()).toBe(false);
+ expect(findSpinner().exists()).toBe(true);
+ expect(findContentWrapper().exists()).toBe(false);
});
it('does not show the skeleton if content loads within CONTENT_WAIT_MS', async () => {
- expect(findExploreSkeleton().exists()).toBe(false);
- expect(findContentWrapper().isVisible()).toBe(false);
+ expect(findSpinner().exists()).toBe(false);
+ expect(findContentWrapper().exists()).toBe(false);
wrapper.vm.onContentLoaded();
await nextTick();
- expect(findContentWrapper().isVisible()).toBe(true);
- expect(findExploreSkeleton().exists()).toBe(false);
+ expect(findContentWrapper().exists()).toBe(true);
+ expect(findSpinner().exists()).toBe(false);
jest.advanceTimersByTime(DEFAULT_TIMERS.CONTENT_WAIT_MS);
await nextTick();
- expect(findContentWrapper().isVisible()).toBe(true);
- expect(findExploreSkeleton().exists()).toBe(false);
+ expect(findContentWrapper().exists()).toBe(true);
+ expect(findSpinner().exists()).toBe(false);
});
it('hides the skeleton after content loads', async () => {
@@ -79,15 +63,15 @@ describe('Skeleton component', () => {
await nextTick();
- expect(findExploreSkeleton().exists()).toBe(true);
- expect(findContentWrapper().isVisible()).toBe(false);
+ expect(findSpinner().exists()).toBe(true);
+ expect(findContentWrapper().exists()).toBe(false);
wrapper.vm.onContentLoaded();
await nextTick();
- expect(findContentWrapper().isVisible()).toBe(true);
- expect(findExploreSkeleton().exists()).toBe(false);
+ expect(findContentWrapper().exists()).toBe(true);
+ expect(findSpinner().exists()).toBe(false);
});
});
@@ -99,7 +83,7 @@ describe('Skeleton component', () => {
await nextTick();
expect(findAlert().exists()).toBe(true);
- expect(findContentWrapper().isVisible()).toBe(false);
+ expect(findContentWrapper().exists()).toBe(false);
});
it('shows the error dialog if content fails to load', async () => {
@@ -110,7 +94,7 @@ describe('Skeleton component', () => {
await nextTick();
expect(findAlert().exists()).toBe(true);
- expect(findContentWrapper().isVisible()).toBe(false);
+ expect(findContentWrapper().exists()).toBe(false);
});
it('does not show the error dialog if content has loaded within TIMEOUT_MS', async () => {
@@ -120,36 +104,28 @@ describe('Skeleton component', () => {
await nextTick();
expect(findAlert().exists()).toBe(false);
- expect(findContentWrapper().isVisible()).toBe(true);
+ expect(findContentWrapper().exists()).toBe(true);
});
});
});
describe('skeleton variant', () => {
- it.each`
- skeletonType | condition | variant
- ${'dashboards'} | ${'variant is dashboards'} | ${SKELETON_VARIANTS[0]}
- ${'explore'} | ${'variant is explore'} | ${SKELETON_VARIANTS[1]}
- ${'manage'} | ${'variant is manage'} | ${SKELETON_VARIANTS[2]}
- ${'embed'} | ${'variant is embed'} | ${SKELETON_VARIANT_EMBED}
- ${'spinner'} | ${'variant is spinner'} | ${'spinner'}
- ${'default'} | ${'variant is not manage, dashboards or explore'} | ${'unknown'}
- `('should render $skeletonType skeleton if $condition', async ({ skeletonType, variant }) => {
- mountComponent({ variant });
+ it('shows only the spinner variant when variant is spinner', async () => {
+ mountComponent({ variant: 'spinner' });
jest.advanceTimersByTime(DEFAULT_TIMERS.CONTENT_WAIT_MS);
await nextTick();
- const showsDefaultSkeleton = ![...SKELETON_VARIANTS, SKELETON_VARIANT_EMBED].includes(
- variant,
- );
- expect(findDashboardsSkeleton().exists()).toBe(skeletonType === SKELETON_VARIANTS[0]);
- expect(findExploreSkeleton().exists()).toBe(skeletonType === SKELETON_VARIANTS[1]);
- expect(findManageSkeleton().exists()).toBe(skeletonType === SKELETON_VARIANTS[2]);
- expect(findEmbedSkeleton().exists()).toBe(skeletonType === SKELETON_VARIANT_EMBED);
+ expect(findSpinner().exists()).toBe(true);
+ expect(wrapper.findComponent(GlSkeletonLoader).exists()).toBe(false);
+ });
- expect(wrapper.findComponent(GlSkeletonLoader).exists()).toBe(showsDefaultSkeleton);
+ it('shows only the default variant when variant is not spinner', async () => {
+ mountComponent({ variant: 'unknown' });
+ jest.advanceTimersByTime(DEFAULT_TIMERS.CONTENT_WAIT_MS);
+ await nextTick();
- expect(wrapper.findComponent(GlLoadingIcon).exists()).toBe(variant === 'spinner');
+ expect(findSpinner().exists()).toBe(false);
+ expect(wrapper.findComponent(GlSkeletonLoader).exists()).toBe(true);
});
});