Commit 98d75c2e authored by Martin Wortschack's avatar Martin Wortschack

Merge branch '33537-update-backend-endpoint-changes' into 'master'

Fix compatibility issues with new backend logs API

Closes #36101

See merge request gitlab-org/gitlab!19752
parents 56846090 8024da58
......@@ -78,7 +78,17 @@ export default {
return axios.delete(url);
},
getPodLogs({ projectFullPath, environmentId, podName, containerName }) {
/**
* Returns pods logs for an environment with an optional pod and container
*
* @param {Object} params
* @param {string} param.projectFullPath - Path of the project, in format `/<namespace>/<project-key>`
* @param {number} param.environmentId - Id of the environment
* @param {string=} params.podName - Pod name, if not set the backend assumes a default one
* @param {string=} params.containerName - Container name, if not set the backend assumes a default one
* @returns {Promise} Axios promise for the result of a GET request of logs
*/
getPodLogs({ projectPath, environmentId, podName, containerName }) {
let logPath = this.podLogsPath;
if (podName && containerName) {
logPath = this.podLogsPathWithPodContainer;
......@@ -87,7 +97,7 @@ export default {
}
let url = this.buildUrl(logPath)
.replace(':project_full_path', projectFullPath)
.replace(':project_full_path', projectPath)
.replace(':environment_id', environmentId);
if (podName) {
......
......@@ -5,16 +5,16 @@ import { isScrolledToBottom, scrollDown, toggleDisableButton } from '~/lib/utils
import httpStatusCodes from '~/lib/utils/http_status';
import LogOutputBehaviours from '~/lib/utils/logoutput_behaviours';
import flash from '~/flash';
import { __, s__, sprintf } from '~/locale';
import { s__, sprintf } from '~/locale';
import _ from 'underscore';
import { backOff } from '~/lib/utils/common_utils';
import Api from 'ee/api';
const TWO_MINUTES = 120000;
const requestWithBackoff = (projectFullPath, environmentId, podName, containerName) =>
const requestWithBackoff = (projectPath, environmentId, podName, containerName) =>
backOff((next, stop) => {
Api.getPodLogs({ projectFullPath, environmentId, podName, containerName })
Api.getPodLogs({ projectPath, environmentId, podName, containerName })
.then(res => {
if (!res.data) {
next();
......@@ -128,7 +128,7 @@ export default class KubernetesPodLogs extends LogOutputBehaviours {
);
}
} else {
flash(__('Environments|An error occurred while fetching the logs'));
flash(s__('Environments|An error occurred while fetching the logs'));
}
})
.finally(() => {
......
<script>
import { mapActions, mapState, mapGetters } from 'vuex';
import { GlDropdown, GlDropdownItem, GlFormGroup, GlButton, GlTooltipDirective } from '@gitlab/ui';
import flash from '~/flash';
import {
canScroll,
isScrolledToTop,
......@@ -10,7 +9,6 @@ import {
scrollUp,
} from '~/lib/utils/scroll_utils';
import Icon from '~/vue_shared/components/icon.vue';
import { __ } from '~/locale';
export default {
components: {
......@@ -24,6 +22,14 @@ export default {
GlTooltip: GlTooltipDirective,
},
props: {
environmentId: {
type: String,
required: true,
},
projectFullPath: {
type: String,
required: true,
},
currentEnvironmentName: {
type: String,
required: false,
......@@ -39,11 +45,6 @@ export default {
required: false,
default: '',
},
logsEndpoint: {
type: String,
required: false,
default: '',
},
},
data() {
return {
......@@ -73,24 +74,19 @@ export default {
window.addEventListener('scroll', this.updateScrollState);
},
mounted() {
this.fetchEnvironments(this.environmentsPath);
this.setInitData({
projectPath: this.projectFullPath,
environmentId: this.environmentId,
podName: this.currentPodName,
});
this.setLogsEndpoint(this.logsEndpoint)
.then(() => {
this.fetchLogs(this.currentPodName);
})
.catch(() => {
flash(__('Something went wrong on our end. Please try again!'));
});
this.fetchEnvironments(this.environmentsPath);
},
destroyed() {
window.removeEventListener('scroll', this.updateScrollState);
},
methods: {
...mapActions('environmentLogs', ['setLogsEndpoint', 'fetchEnvironments', 'fetchLogs']),
showPod(podName) {
this.fetchLogs(podName);
},
...mapActions('environmentLogs', ['setInitData', 'showPodLogs', 'fetchEnvironments']),
updateScrollState() {
this.scrollToTopEnabled = canScroll() && !isScrolledToTop();
this.scrollToBottomEnabled = canScroll() && !isScrolledToBottom();
......@@ -136,7 +132,7 @@ export default {
>
<gl-dropdown
id="pods-dropdown"
:text="pods.current"
:text="pods.current || s__('Environments|No pods to display')"
:disabled="logs.isLoading"
class="d-flex js-pods-dropdown"
toggle-class="dropdown-menu-toggle"
......@@ -144,7 +140,7 @@ export default {
<gl-dropdown-item
v-for="podName in pods.options"
:key="podName"
@click="showPod(podName)"
@click="showPodLogs(podName)"
>
{{ podName }}
</gl-dropdown-item>
......@@ -188,7 +184,7 @@ export default {
class="ml-1 px-2 js-refresh-log"
:title="__('Refresh')"
:aria-label="__('Refresh')"
@click="showPod(pods.current)"
@click="showPodLogs(pods.current)"
>
<icon name="retry" />
</gl-button>
......
import { backOff } from '~/lib/utils/common_utils';
import httpStatusCodes from '~/lib/utils/http_status';
import axios from '~/lib/utils/axios_utils';
import flash from '~/flash';
import { s__ } from '~/locale';
import Api from 'ee/api';
import * as types from './mutation_types';
const requestUntilData = (url, params) =>
const requestLogsUntilData = ({ projectPath, environmentId, podName }) =>
backOff((next, stop) => {
axios
.get(url, {
params,
})
Api.getPodLogs({ projectPath, environmentId, podName })
.then(res => {
if (!res.data) {
if (res.status === httpStatusCodes.ACCEPTED) {
next();
return;
}
......@@ -22,8 +21,15 @@ const requestUntilData = (url, params) =>
});
});
export const setLogsEndpoint = ({ commit }, logsEndpoint) => {
commit(types.SET_LOGS_ENDPOINT, logsEndpoint);
export const setInitData = ({ dispatch, commit }, { projectPath, environmentId, podName }) => {
commit(types.SET_PROJECT_ENVIRONMENT, { projectPath, environmentId });
commit(types.SET_CURRENT_POD_NAME, podName);
dispatch('fetchLogs');
};
export const showPodLogs = ({ dispatch, commit }, podName) => {
commit(types.SET_CURRENT_POD_NAME, podName);
dispatch('fetchLogs');
};
export const fetchEnvironments = ({ commit }, environmentsPath) => {
......@@ -40,20 +46,20 @@ export const fetchEnvironments = ({ commit }, environmentsPath) => {
});
};
export const fetchLogs = ({ commit, state }, podName) => {
if (podName) {
commit(types.SET_CURRENT_POD_NAME, podName);
}
export const fetchLogs = ({ commit, state }) => {
const params = {
projectPath: state.projectPath,
environmentId: state.environments.current,
podName: state.pods.current,
};
commit(types.REQUEST_PODS_DATA);
commit(types.REQUEST_LOGS_DATA);
return requestUntilData(state.logs.endpoint, { pod_name: podName })
.then(({ data }) => {
const { pods, logs } = data;
// Set first pod as default, if none is set
if (!podName && pods[0]) {
commit(types.SET_CURRENT_POD_NAME, pods[0]);
}
return requestLogsUntilData(params)
.then(({ data }) => {
const { pod_name, pods, logs } = data;
commit(types.SET_CURRENT_POD_NAME, pod_name);
commit(types.RECEIVE_PODS_DATA_SUCCESS, pods);
commit(types.RECEIVE_LOGS_DATA_SUCCESS, logs);
......
export const SET_LOGS_ENDPOINT = 'SET_LOGS_ENDPOINT';
export const SET_CURRENT_POD_NAME = 'SET_CURRENT_POD_NAME';
export const SET_PROJECT_ENVIRONMENT = 'SET_PROJECT_ENVIRONMENT';
export const REQUEST_ENVIRONMENTS_DATA = 'REQUEST_ENVIRONMENTS_DATA';
export const RECEIVE_ENVIRONMENTS_DATA_SUCCESS = 'RECEIVE_ENVIRONMENTS_DATA_SUCCESS';
......@@ -9,6 +8,7 @@ export const REQUEST_LOGS_DATA = 'REQUEST_LOGS_DATA';
export const RECEIVE_LOGS_DATA_SUCCESS = 'RECEIVE_LOGS_DATA_SUCCESS';
export const RECEIVE_LOGS_DATA_ERROR = 'RECEIVE_LOGS_DATA_ERROR';
export const SET_CURRENT_POD_NAME = 'SET_CURRENT_POD_NAME';
export const REQUEST_PODS_DATA = 'REQUEST_PODS_DATA';
export const RECEIVE_PODS_DATA_SUCCESS = 'RECEIVE_PODS_DATA_SUCCESS';
export const RECEIVE_PODS_DATA_ERROR = 'RECEIVE_PODS_DATA_ERROR';
import * as types from './mutation_types';
export default {
[types.SET_LOGS_ENDPOINT](state, endpoint) {
state.logs.endpoint = endpoint;
},
[types.SET_CURRENT_POD_NAME](state, podName) {
state.pods.current = podName;
/** Project data */
[types.SET_PROJECT_ENVIRONMENT](state, { projectPath, environmentId }) {
state.projectPath = projectPath;
state.environments.current = environmentId;
},
/** Environments data */
[types.REQUEST_ENVIRONMENTS_DATA](state) {
state.environments.options = [];
state.environments.isLoading = true;
......@@ -21,6 +21,7 @@ export default {
state.environments.isLoading = false;
},
/** Logs data */
[types.REQUEST_LOGS_DATA](state) {
state.logs.lines = [];
state.logs.isLoading = true;
......@@ -37,6 +38,10 @@ export default {
state.logs.isComplete = true;
},
/** Pods data */
[types.SET_CURRENT_POD_NAME](state, podName) {
state.pods.current = podName;
},
[types.REQUEST_PODS_DATA](state) {
state.pods.options = [];
},
......
export default () => ({
/**
* Current project path
*/
projectPath: '',
/**
* Environments list information
*/
environments: {
options: [],
isLoading: false,
current: null,
},
/**
* Logs including trace
*/
logs: {
endpoint: null,
lines: [],
isLoading: false,
isComplete: true,
......
......@@ -164,7 +164,7 @@ describe('Api', () => {
});
describe('getPodLogs', () => {
const projectFullPath = 'root/test-project';
const projectPath = 'root/test-project';
const environmentId = 2;
const podName = 'pod';
const containerName = 'container';
......@@ -180,9 +180,9 @@ describe('Api', () => {
});
it('calls `axios.get` with pod_name and container_name', done => {
const expectedUrl = `${dummyUrlRoot}/${projectFullPath}/environments/${environmentId}/pods/${podName}/containers/${containerName}/logs.json`;
const expectedUrl = `${dummyUrlRoot}/${projectPath}/environments/${environmentId}/pods/${podName}/containers/${containerName}/logs.json`;
Api.getPodLogs({ projectFullPath, environmentId, podName, containerName })
Api.getPodLogs({ projectPath, environmentId, podName, containerName })
.then(() => {
expect(expectedUrl).toBe(lastUrl());
})
......@@ -191,9 +191,9 @@ describe('Api', () => {
});
it('calls `axios.get` without pod_name and container_name', done => {
const expectedUrl = `${dummyUrlRoot}/${projectFullPath}/environments/${environmentId}/pods/containers/logs.json`;
const expectedUrl = `${dummyUrlRoot}/${projectPath}/environments/${environmentId}/pods/containers/logs.json`;
Api.getPodLogs({ projectFullPath, environmentId })
Api.getPodLogs({ projectPath, environmentId })
.then(() => {
expect(expectedUrl).toBe(lastUrl());
})
......@@ -202,9 +202,9 @@ describe('Api', () => {
});
it('calls `axios.get` with pod_name', done => {
const expectedUrl = `${dummyUrlRoot}/${projectFullPath}/environments/${environmentId}/pods/${podName}/containers/logs.json`;
const expectedUrl = `${dummyUrlRoot}/${projectPath}/environments/${environmentId}/pods/${podName}/containers/logs.json`;
Api.getPodLogs({ projectFullPath, environmentId, podName })
Api.getPodLogs({ projectPath, environmentId, podName })
.then(() => {
expect(expectedUrl).toBe(lastUrl());
})
......
......@@ -11,12 +11,14 @@ import {
import EnvironmentLogs from 'ee/logs/components/environment_logs.vue';
import { createStore } from 'ee/logs/stores';
import {
mockEnvironment,
mockProjectPath,
mockEnvId,
mockEnvName,
mockEnvironments,
mockPods,
mockEnvironmentsEndpoint,
mockLines,
mockLogsEndpoint,
mockPodName,
mockEnvironmentsEndpoint,
} from '../mock_data';
jest.mock('~/lib/utils/scroll_utils');
......@@ -28,13 +30,16 @@ describe('EnvironmentLogs', () => {
let state;
const propsData = {
currentEnvironmentName: mockEnvironment.name,
environmentId: mockEnvId,
projectFullPath: mockProjectPath,
currentEnvironmentName: mockEnvName,
environmentsPath: mockEnvironmentsEndpoint,
logsEndpoint: mockLogsEndpoint,
};
const actionMocks = {
setInitData: jest.fn(),
showPodLogs: jest.fn(),
fetchEnvironments: jest.fn(),
fetchLogs: jest.fn(),
};
const findEnvironmentsDropdown = () => wrapper.find('.js-environments-dropdown');
......@@ -60,6 +65,12 @@ describe('EnvironmentLogs', () => {
EnvironmentLogsComponent = Vue.extend(EnvironmentLogs);
});
afterEach(() => {
actionMocks.setInitData.mockReset();
actionMocks.showPodLogs.mockReset();
actionMocks.fetchEnvironments.mockReset();
});
it('displays UI elements', () => {
initWrapper();
......@@ -76,17 +87,32 @@ describe('EnvironmentLogs', () => {
expect(findLogTrace().isEmpty()).toBe(false);
});
it('mounted inits data', () => {
initWrapper();
expect(actionMocks.setInitData).toHaveBeenCalledTimes(1);
expect(actionMocks.setInitData).toHaveBeenLastCalledWith({
environmentId: mockEnvId,
projectPath: mockProjectPath,
podName: null,
});
expect(actionMocks.fetchEnvironments).toHaveBeenCalledTimes(1);
expect(actionMocks.fetchEnvironments).toHaveBeenLastCalledWith(mockEnvironmentsEndpoint);
expect(findEnvironmentsDropdown().props('text')).toBe(mockEnvName);
expect(findPodsDropdown().props('text').length).toBeGreaterThan(0);
});
describe('loading state', () => {
beforeEach(() => {
actionMocks.fetchEnvironments.mockImplementation(() => {
state.environments.options = [];
state.environments.isLoading = true;
});
actionMocks.fetchLogs.mockImplementation(() => {
state.pods.options = [];
state.logs.lines = [];
state.logs.isLoading = true;
});
state.pods.options = [];
state.logs.lines = [];
state.logs.isLoading = true;
state.environments.options = [];
state.environments.isLoading = true;
initWrapper();
});
......@@ -102,24 +128,34 @@ describe('EnvironmentLogs', () => {
});
it('shows a logs trace', () => {
const trace = findLogTrace();
expect(trace.text()).toBe('');
expect(trace.find('.js-build-loader-animation').isVisible()).toBe(true);
expect(findLogTrace().text()).toBe('');
expect(
findLogTrace()
.find('.js-build-loader-animation')
.isVisible(),
).toBe(true);
});
});
describe('state with data', () => {
beforeEach(() => {
actionMocks.fetchEnvironments.mockImplementation(() => {
state.environments.options = mockEnvironments;
});
actionMocks.fetchLogs.mockImplementation(() => {
actionMocks.setInitData.mockImplementation(() => {
state.pods.options = mockPods;
[state.pods.current] = state.pods.options;
state.logs.isComplete = false;
state.logs.lines = mockLines;
});
actionMocks.showPodLogs.mockImplementation(podName => {
state.pods.options = mockPods;
[state.pods.current] = podName;
state.logs.isComplete = false;
state.logs.lines = mockLines;
});
actionMocks.fetchEnvironments.mockImplementation(() => {
state.environments.options = mockEnvironments;
});
initWrapper();
});
......@@ -128,13 +164,15 @@ describe('EnvironmentLogs', () => {
scrollDown.mockReset();
scrollUp.mockReset();
actionMocks.setInitData.mockReset();
actionMocks.showPodLogs.mockReset();
actionMocks.fetchEnvironments.mockReset();
actionMocks.fetchLogs.mockReset();
});
it('populates environments dropdown', () => {
const items = findEnvironmentsDropdown().findAll(GlDropdownItem);
expect(findEnvironmentsDropdown().props('text')).toBe(mockEnvName);
expect(items.length).toBe(mockEnvironments.length);
mockEnvironments.forEach((env, i) => {
const item = items.at(i);
......@@ -147,6 +185,7 @@ describe('EnvironmentLogs', () => {
it('populates pods dropdown', () => {
const items = findPodsDropdown().findAll(GlDropdownItem);
expect(findPodsDropdown().props('text')).toBe(mockPodName);
expect(items.length).toBe(mockPods.length);
mockPods.forEach((pod, i) => {
const item = items.at(i);
......@@ -169,28 +208,26 @@ describe('EnvironmentLogs', () => {
const items = findPodsDropdown().findAll(GlDropdownItem);
const index = 2; // any pod
expect(actionMocks.fetchLogs).toHaveBeenCalledTimes(1);
expect(actionMocks.fetchLogs).toHaveBeenLastCalledWith(null);
expect(actionMocks.showPodLogs).toHaveBeenCalledTimes(0);
items.at(index).vm.$emit('click');
expect(actionMocks.fetchLogs).toHaveBeenCalledTimes(2);
expect(actionMocks.fetchLogs).toHaveBeenLastCalledWith(mockPods[index]);
expect(actionMocks.showPodLogs).toHaveBeenCalledTimes(1);
expect(actionMocks.showPodLogs).toHaveBeenLastCalledWith(mockPods[index]);
});
it('refresh button, trace is refreshed', () => {
expect(actionMocks.fetchLogs).toHaveBeenCalledTimes(1);
expect(actionMocks.fetchLogs).toHaveBeenLastCalledWith(null);
expect(actionMocks.showPodLogs).toHaveBeenCalledTimes(0);
findRefreshLog().vm.$emit('click'); // works
findRefreshLog().vm.$emit('click');
expect(actionMocks.fetchLogs).toHaveBeenCalledTimes(2);
expect(actionMocks.fetchLogs).toHaveBeenLastCalledWith(mockPods[0]);
expect(actionMocks.showPodLogs).toHaveBeenCalledTimes(1);
expect(actionMocks.showPodLogs).toHaveBeenLastCalledWith(mockPodName);
});
describe('when scrolling actions are enabled', () => {
beforeEach(done => {
// simulate being in the middle of a long page
// mock scrolled to the middle of a long page
canScroll.mockReturnValue(true);
isScrolledToBottom.mockReturnValue(false);
isScrolledToTop.mockReturnValue(false);
......@@ -215,13 +252,13 @@ describe('EnvironmentLogs', () => {
it('click on "scroll to bottom" scrolls down', () => {
expect(findScrollToBottom().is('[disabled]')).toBe(false);
findScrollToBottom().vm.$emit('click');
expect(scrollDown).toHaveBeenCalledTimes(2); // plus one time when loaded
expect(scrollDown).toHaveBeenCalledTimes(2); // plus one time when trace was loaded
});
});
describe('when scrolling actions are disabled', () => {
beforeEach(() => {
// a short page, without a scrollbar
// mock a short page without a scrollbar
canScroll.mockReturnValue(false);
isScrolledToBottom.mockReturnValue(true);
isScrolledToTop.mockReturnValue(true);
......
const makeMockLogsPath = id => `/root/autodevops-deploy/environments/${id}/logs`;
export const mockProjectPath = 'root/autodevops-deploy';
export const mockEnvName = 'production';
export const mockEnvironmentsEndpoint = `${mockProjectPath}/environments.json`;
export const mockEnvId = '99';
const makeMockEnvironment = (id, name) => ({
id,
logs_path: makeMockLogsPath(id),
logs_path: `${mockProjectPath}/environments/${id}/logs`,
name,
});
export const mockEnvironment = makeMockEnvironment(99, 'production');
export const mockEnvironmentsEndpoint = '/root/autodevops-deploy/environments.json';
export const mockEnvironment = makeMockEnvironment(mockEnvId, mockEnvName);
export const mockEnvironments = [
mockEnvironment,
makeMockEnvironment(101, 'staging'),
......@@ -21,7 +24,6 @@ export const mockPods = [
'production-764c58d697-ddddd',
];
export const mockLogsEndpoint = `/root/autodevops-deploy/environments/${mockEnvironment.id}/logs.json`;
export const mockLines = [
'10.36.0.1 - - [16/Oct/2019:06:29:48 UTC] "GET / HTTP/1.1" 200 13',
'- -> /',
......
......@@ -4,17 +4,18 @@ import axios from '~/lib/utils/axios_utils';
import testAction from 'helpers/vuex_action_helper';
import * as types from 'ee/logs/stores/mutation_types';
import logsPageState from 'ee/logs/stores/state';
import { setLogsEndpoint, fetchEnvironments, fetchLogs } from 'ee/logs/stores/actions';
import { setInitData, showPodLogs, fetchEnvironments, fetchLogs } from 'ee/logs/stores/actions';
import flash from '~/flash';
import {
mockLogsEndpoint,
mockProjectPath,
mockEnvId,
mockPodName,
mockEnvironmentsEndpoint,
mockEnvironments,
mockPods,
mockPodName,
mockLines,
mockEnvironmentsEndpoint,
} from '../mock_data';
jest.mock('~/flash');
......@@ -31,14 +32,33 @@ describe('Logs Store actions', () => {
flash.mockClear();
});
describe('setLogsEndpoint', () => {
it('should commit SET_LOGS_ENDPOINT mutation', done => {
describe('setInitData', () => {
it('should commit environment and pod name mutation', done => {
testAction(
setLogsEndpoint,
mockLogsEndpoint,
setInitData,
{ projectPath: mockProjectPath, environmentId: mockEnvId, podName: mockPodName },
state,
[{ type: types.SET_LOGS_ENDPOINT, payload: mockLogsEndpoint }],
[],
[
{
type: types.SET_PROJECT_ENVIRONMENT,
payload: { projectPath: mockProjectPath, environmentId: mockEnvId },
},
{ type: types.SET_CURRENT_POD_NAME, payload: mockPodName },
],
[{ type: 'fetchLogs' }],
done,
);
});
});
describe('showPodLogs', () => {
it('should commit pod name', done => {
testAction(
showPodLogs,
mockPodName,
state,
[{ type: types.SET_CURRENT_POD_NAME, payload: mockPodName }],
[{ type: 'fetchLogs' }],
done,
);
});
......@@ -81,24 +101,6 @@ describe('Logs Store actions', () => {
},
);
});
it('should commit RECEIVE_ENVIRONMENTS_DATA_ERROR on error', done => {
mock.onGet('/root/autodevops-deploy/environments.json').replyOnce(500);
testAction(
fetchEnvironments,
'/root/autodevops-deploy/environments.json',
state,
[
{ type: types.REQUEST_ENVIRONMENTS_DATA },
{ type: types.RECEIVE_ENVIRONMENTS_DATA_ERROR },
],
[],
() => {
expect(flash).toHaveBeenCalledTimes(1);
done();
},
);
});
});
describe('fetchLogs', () => {
......@@ -106,22 +108,33 @@ describe('Logs Store actions', () => {
mock = new MockAdapter(axios);
});
afterEach(() => {
mock.reset();
});
it('should commit logs and pod data when there is pod name defined', done => {
state.logs.endpoint = mockLogsEndpoint;
state.projectPath = mockProjectPath;
state.environments.current = mockEnvId;
state.pods.current = mockPodName;
mock.onGet(mockLogsEndpoint).replyOnce(200, {
const endpoint = `/${mockProjectPath}/environments/${mockEnvId}/pods/${mockPodName}/containers/logs.json`;
mock.onGet(endpoint).reply(200, {
pod_name: mockPodName,
pods: mockPods,
logs: mockLines,
});
mock.onGet(endpoint).replyOnce(202); // mock reactive cache
testAction(
fetchLogs,
mockPodName,
null,
state,
[
{ type: types.SET_CURRENT_POD_NAME, payload: mockPodName },
{ type: types.REQUEST_PODS_DATA },
{ type: types.REQUEST_LOGS_DATA },
{ type: types.SET_CURRENT_POD_NAME, payload: mockPodName },
{ type: types.RECEIVE_PODS_DATA_SUCCESS, payload: mockPods },
{ type: types.RECEIVE_LOGS_DATA_SUCCESS, payload: mockLines },
],
......@@ -131,12 +144,17 @@ describe('Logs Store actions', () => {
});
it('should commit logs and pod data when no pod name defined', done => {
state.logs.endpoint = mockLogsEndpoint;
state.projectPath = mockProjectPath;
state.environments.current = mockEnvId;
mock.onGet(mockLogsEndpoint).replyOnce(200, {
const endpoint = `/${mockProjectPath}/environments/${mockEnvId}/pods/containers/logs.json`;
mock.onGet(endpoint).reply(200, {
pod_name: mockPodName,
pods: mockPods,
logs: mockLines,
});
mock.onGet(endpoint).replyOnce(202); // mock reactive cache
testAction(
fetchLogs,
......@@ -145,7 +163,7 @@ describe('Logs Store actions', () => {
[
{ type: types.REQUEST_PODS_DATA },
{ type: types.REQUEST_LOGS_DATA },
{ type: types.SET_CURRENT_POD_NAME, payload: mockPods[0] },
{ type: types.SET_CURRENT_POD_NAME, payload: mockPodName },
{ type: types.RECEIVE_PODS_DATA_SUCCESS, payload: mockPods },
{ type: types.RECEIVE_LOGS_DATA_SUCCESS, payload: mockLines },
],
......@@ -154,17 +172,18 @@ describe('Logs Store actions', () => {
);
});
it('should commit logs and pod errors', done => {
state.logs.endpoint = mockLogsEndpoint;
it('should commit logs and pod errors when backend fails', done => {
state.projectPath = mockProjectPath;
state.environments.current = mockEnvId;
mock.onGet(mockLogsEndpoint).replyOnce(500);
const endpoint = `/${mockProjectPath}/environments/${mockEnvId}/pods/containers/logs.json`;
mock.onGet(endpoint).replyOnce(500);
testAction(
fetchLogs,
mockPodName,
null,
state,
[
{ type: types.SET_CURRENT_POD_NAME, payload: mockPodName },
{ type: types.REQUEST_PODS_DATA },
{ type: types.REQUEST_LOGS_DATA },
{ type: types.RECEIVE_PODS_DATA_ERROR },
......
......@@ -2,7 +2,14 @@ import mutations from 'ee/logs/stores/mutations';
import * as types from 'ee/logs/stores/mutation_types';
import logsPageState from 'ee/logs/stores/state';
import { mockLogsEndpoint, mockEnvironments, mockPods, mockPodName, mockLines } from '../mock_data';
import {
mockProjectPath,
mockEnvId,
mockEnvironments,
mockPods,
mockPodName,
mockLines,
} from '../mock_data';
describe('Logs Store Mutations', () => {
let state;
......@@ -17,17 +24,14 @@ describe('Logs Store Mutations', () => {
});
});
describe('SET_LOGS_ENDPOINT', () => {
describe('SET_PROJECT_ENVIRONMENT', () => {
it('sets the logs json endpoint', () => {
mutations[types.SET_LOGS_ENDPOINT](state, mockLogsEndpoint);
expect(state.logs.endpoint).toEqual(mockLogsEndpoint);
});
});
describe('SET_CURRENT_POD_NAME', () => {
it('sets current pod name', () => {
mutations[types.SET_CURRENT_POD_NAME](state, mockPodName);
expect(state.pods.current).toEqual(mockPodName);
mutations[types.SET_PROJECT_ENVIRONMENT](state, {
projectPath: mockProjectPath,
environmentId: mockEnvId,
});
expect(state.projectPath).toEqual(mockProjectPath);
expect(state.environments.current).toEqual(mockEnvId);
});
});
......@@ -57,6 +61,7 @@ describe('Logs Store Mutations', () => {
expect(state.environments).toEqual({
options: [],
isLoading: false,
current: null,
});
});
});
......@@ -103,6 +108,13 @@ describe('Logs Store Mutations', () => {
});
});
describe('SET_CURRENT_POD_NAME', () => {
it('set current pod name', () => {
mutations[types.SET_CURRENT_POD_NAME](state, mockPodName);
expect(state.pods.current).toEqual(mockPodName);
});
});
describe('REQUEST_PODS_DATA', () => {
it('receives log data error and stops loading', () => {
mutations[types.REQUEST_PODS_DATA](state);
......
......@@ -6442,6 +6442,9 @@ msgstr ""
msgid "Environments|No deployments yet"
msgstr ""
msgid "Environments|No pods to display"
msgstr ""
msgid "Environments|Note that this action will stop the environment, but it will %{emphasisStart}not%{emphasisEnd} have an effect on any existing deployment due to no “stop environment action” being defined in the %{ciConfigLinkStart}.gitlab-ci.yml%{ciConfigLinkEnd} file."
msgstr ""
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment