提交 14b508bd 编写于 作者: T Tomas Vik

Merge branch '263-refactor-issue-provider' into 'main'

fix: custom queries don't work with scoped labels

See merge request gitlab-org/gitlab-vscode-extension!128
module.exports = {
TreeItem: jest.fn(),
ThemeIcon: jest.fn(),
EventEmitter: jest.fn(),
TreeItemCollapsibleState: {
Collapsed: 'collapsed',
},
};
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
<path fill="#C5C5C5" fill-rule="evenodd" d="M8,8.17157 L13,3.17157 L13,3 L3,3 L3,3.17157 L8,8.17157 Z M7.49796,15.8664 L9.49796,14.718 C9.80851,14.5396 10,14.2089 10,13.8508 L10,9 L14.7071,4.29289 C14.8946,4.10536 15,3.851 15,3.58579 L15,2 C15,1.44772 14.5523,1 14,1 L2,1 C1.44772,1 1,1.44772 1,2 L1,3.58579 C1,3.851 1.10536,4.10536 1.29289,4.29289 L6,9 L6,14.9992 C6,15.768 6.8313,16.2492 7.49796,15.8664 Z"/>
</svg>
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
<path fill="#C5C5C5" fill-rule="evenodd" d="M3,1 L9.17157,1 C9.64307222,1 10.0973893,1.16648691 10.4559723,1.46691468 L10.5858,1.58579 L13.4142,4.41421 C13.7476222,4.74761444 13.9511481,5.18659519 13.9922598,5.65257532 L14,5.82843 L14,14 C14,14.51285 13.613973,14.9355092 13.1166239,14.9932725 L13,15 L3,15 C2.48716857,15 2.06449347,14.613973 2.0067278,14.1166239 L2,14 L2,2 C2,1.48716857 2.38604429,1.06449347 2.88337975,1.0067278 L3,1 L9.17157,1 L3,1 Z M9,3 L4,3 L4,13 L12,13 L12,6 L10,6 C9.48715929,6 9.06449214,5.61395571 9.00672766,5.11662025 L9,5 L9,3 Z M6,10 L8,10 C8.55228,10 9,10.4477 9,11 C9,11.51285 8.61395571,11.9355092 8.11662025,11.9932725 L8,12 L6,12 C5.44772,12 5,11.5523 5,11 C5,10.48715 5.38604429,10.0644908 5.88337975,10.0067275 L6,10 Z M10,7 C10.5523,7 11,7.44772 11,8 C11,8.55228 10.5523,9 10,9 L6,9 C5.44772,9 5,8.55228 5,8 C5,7.44772 5.44772,7 6,7 L10,7 Z"/>
</svg>
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
<path fill="#424242" fill-rule="evenodd" d="M8,8.17157 L13,3.17157 L13,3 L3,3 L3,3.17157 L8,8.17157 Z M7.49796,15.8664 L9.49796,14.718 C9.80851,14.5396 10,14.2089 10,13.8508 L10,9 L14.7071,4.29289 C14.8946,4.10536 15,3.851 15,3.58579 L15,2 C15,1.44772 14.5523,1 14,1 L2,1 C1.44772,1 1,1.44772 1,2 L1,3.58579 C1,3.851 1.10536,4.10536 1.29289,4.29289 L6,9 L6,14.9992 C6,15.768 6.8313,16.2492 7.49796,15.8664 Z"/>
</svg>
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
<path fill="#424242" fill-rule="evenodd" d="M3,1 L9.17157,1 C9.64307222,1 10.0973893,1.16648691 10.4559723,1.46691468 L10.5858,1.58579 L13.4142,4.41421 C13.7476222,4.74761444 13.9511481,5.18659519 13.9922598,5.65257532 L14,5.82843 L14,14 C14,14.51285 13.613973,14.9355092 13.1166239,14.9932725 L13,15 L3,15 C2.48716857,15 2.06449347,14.613973 2.0067278,14.1166239 L2,14 L2,2 C2,1.48716857 2.38604429,1.06449347 2.88337975,1.0067278 L3,1 L9.17157,1 L3,1 Z M9,3 L4,3 L4,13 L12,13 L12,6 L10,6 C9.48715929,6 9.06449214,5.61395571 9.00672766,5.11662025 L9,5 L9,3 Z M6,10 L8,10 C8.55228,10 9,10.4477 9,11 C9,11.51285 8.61395571,11.9355092 8.11662025,11.9932725 L8,12 L6,12 C5.44772,12 5,11.5523 5,11 C5,10.48715 5.38604429,10.0644908 5.88337975,10.0067275 L6,10 Z M10,7 C10.5523,7 11,7.44772 11,8 C11,8.55228 10.5523,9 10,9 L6,9 C5.44772,9 5,8.55228 5,8 C5,7.44772 5.44772,7 6,7 L10,7 Z"/>
</svg>
const vscode = require('vscode');
const { SidebarTreeItem } = require('./sidebar_tree_item');
const gitLabService = require('../gitlab_service');
const { handleError } = require('../log');
const ErrorItem = require('./error_item');
const typeToSignMap = {
issues: '#',
epics: '&',
snippets: '$',
vulnerabilities: '-',
};
class CustomQueryItem extends vscode.TreeItem {
constructor(customQuery, project, showProject = false) {
super(
showProject ? project.label : customQuery.name,
vscode.TreeItemCollapsibleState.Collapsed,
);
this.project = project;
this.customQuery = customQuery;
this.iconPath = showProject ? new vscode.ThemeIcon('project') : new vscode.ThemeIcon('filter');
}
async getProjectIssues() {
const items = [];
const issues = await gitLabService.fetchIssuables(this.customQuery, this.project.uri);
const issuableSign = typeToSignMap[this.customQuery.type] || '!';
if (issues.length) {
issues.forEach(issue => {
let title = `${issuableSign}${issue.iid} · ${issue.title}`;
if (issuableSign === '$') {
title = `${issuableSign}${issue.id} · ${issue.title}`;
} else if (issuableSign === '-') {
title = `[${issue.severity}] - ${issue.name}`;
}
items.push(
new SidebarTreeItem(title, issue, this.customQuery.type, null, this.project.uri),
);
});
} else {
const noItemText = this.customQuery.noItemText || 'No items found.';
items.push(new SidebarTreeItem(noItemText));
}
return items;
}
async getChildren() {
try {
return this.getProjectIssues();
} catch (e) {
handleError(e);
return [new ErrorItem()];
}
}
}
exports.CustomQueryItem = CustomQueryItem;
const vscode = require('vscode');
const { CustomQueryItem } = require('./custom_query_item');
describe('CustomQueryItem', () => {
const customQuery = { name: 'Query name' };
const project = { label: 'Project label' };
// eslint-disable-next-line no-unused-vars
let item;
describe('item labeled as a query', () => {
beforeEach(() => {
item = new CustomQueryItem(customQuery, project);
});
it('should have query name as label', () => {
expect(vscode.TreeItem).toBeCalledWith(
'Query name',
vscode.TreeItemCollapsibleState.Collapsed,
);
});
it('should have filter icon', () => {
expect(vscode.ThemeIcon).toHaveBeenCalledWith('filter');
});
});
describe('item labeled as a project', () => {
beforeEach(() => {
item = new CustomQueryItem(customQuery, project, true);
});
it('should have project label as label', () => {
expect(vscode.TreeItem).toBeCalledWith(
'Project label',
vscode.TreeItemCollapsibleState.Collapsed,
);
});
it('should have project icon', () => {
expect(vscode.ThemeIcon).toHaveBeenCalledWith('project');
});
});
});
const vscode = require('vscode');
const gitLabService = require('../gitlab_service');
const { CustomQueryItem } = require('./custom_query_item');
const { MultirootCustomQueryItem } = require('./multiroot_custom_query_item');
const { SidebarTreeItem } = require('./sidebar_tree_item');
const ErrorItem = require('./error_item');
const { handleError } = require('../log');
const gitLabService = require('../gitlab_service');
class DataProvider {
constructor() {
......@@ -15,94 +15,14 @@ class DataProvider {
}
// eslint-disable-next-line class-methods-use-this
async getProjectIssues(parameters, projectUri) {
const items = [];
const issues = await gitLabService.fetchIssuables(parameters, projectUri);
let issuableSign = '!';
if (parameters.type === 'issues') {
issuableSign = '#';
} else if (parameters.type === 'epics') {
issuableSign = '&';
} else if (parameters.type === 'snippets') {
issuableSign = '$';
} else if (parameters.type === 'vulnerabilities') {
issuableSign = '-';
}
if (issues.length) {
issues.forEach(issue => {
let title = `${issuableSign}${issue.iid} · ${issue.title}`;
if (issuableSign === '$') {
title = `${issuableSign}${issue.id} · ${issue.title}`;
} else if (issuableSign === '-') {
title = `[${issue.severity}] - ${issue.name}`;
}
items.push(new SidebarTreeItem(title, issue, parameters.type, null, projectUri));
});
} else {
const noItemText = parameters.noItemText || 'No items found.';
items.push(new SidebarTreeItem(noItemText));
}
return items;
}
async getChildren(el) {
try {
return await this.collectIssuables(el);
} catch (e) {
handleError(e);
return [new ErrorItem()];
}
}
async collectIssuables(el) {
const { customQueries } = vscode.workspace.getConfiguration('gitlab');
if (el) return el.getChildren(el);
const projects = await gitLabService.getAllGitlabProjects();
let items = [];
if (el) {
if (el.contextValue && el.contextValue.startsWith('custom-query-')) {
const customQuery = el.contextValue.split('custom-query-')[1];
const parameters = {};
customQuery.split(';').forEach(cq => {
const key = cq.split(':')[0];
const value = cq.split(':')[1];
parameters[key] = value;
});
if (parameters.project_uri) {
items = await this.getProjectIssues(parameters, parameters.project_uri);
} else if (projects.length > 1) {
projects.forEach(project => {
items.push(
new SidebarTreeItem(
project.label,
parameters,
'project',
vscode.TreeItemCollapsibleState.Collapsed,
project.uri,
),
);
});
} else if (projects.length === 1) {
items = await this.getProjectIssues(parameters, projects[0].uri);
} else {
items.push(new SidebarTreeItem(parameters.noItemText));
}
}
} else {
customQueries.forEach(customQuery => {
items.push(
new SidebarTreeItem(
customQuery.name,
customQuery,
'custom_query',
vscode.TreeItemCollapsibleState.Collapsed,
null,
),
);
});
}
return items;
const { customQueries } = vscode.workspace.getConfiguration('gitlab');
if (projects.length === 0) return new SidebarTreeItem('No projects found');
if (projects.length === 1)
return customQueries.map(customQuery => new CustomQueryItem(customQuery, projects[0]));
return customQueries.map(customQuery => new MultirootCustomQueryItem(customQuery, projects));
}
// eslint-disable-next-line class-methods-use-this
......
const vscode = require('vscode');
const { CustomQueryItem } = require('./custom_query_item');
class MultirootCustomQueryItem extends vscode.TreeItem {
constructor(customQuery, projects) {
super(customQuery.name, vscode.TreeItemCollapsibleState.Collapsed);
this.customQuery = customQuery;
this.projects = projects;
this.iconPath = new vscode.ThemeIcon('filter');
}
async getChildren() {
return this.projects.map(p => new CustomQueryItem(this.customQuery, p, true));
}
}
exports.MultirootCustomQueryItem = MultirootCustomQueryItem;
jest.mock('./custom_query_item');
const vscode = require('vscode');
const { MultirootCustomQueryItem } = require('./multiroot_custom_query_item');
const { CustomQueryItem } = require('./custom_query_item');
describe('MultirootCustomQueryItem', () => {
const customQuery = { name: 'Query name' };
let item;
beforeEach(() => {
const projects = ['a', 'b'];
item = new MultirootCustomQueryItem(customQuery, projects);
});
it('should use query name to create collapsed item', () => {
expect(vscode.TreeItem).toBeCalledWith('Query name', vscode.TreeItemCollapsibleState.Collapsed);
});
it('should return custom query children', async () => {
CustomQueryItem.mockImplementation((query, project, showProject) => ({
query,
project,
showProject,
}));
const [a, b] = await item.getChildren();
expect(a).toEqual({ query: customQuery, project: 'a', showProject: true });
expect(b).toEqual({ query: customQuery, project: 'b', showProject: true });
});
});
......@@ -15,7 +15,7 @@ class SidebarTreeItem extends vscode.TreeItem {
iconPathLight = `/assets/images/light/${type}.svg`;
iconPathDark = `/assets/images/dark/${type}.svg`;
if (type === 'custom_query' || data == null) {
if (data == null) {
command = '';
arg = null;
} else if (type === 'pipelines') {
......@@ -30,24 +30,10 @@ class SidebarTreeItem extends vscode.TreeItem {
arg = [vscode.Uri.parse(data.web_url)];
}
if (type === 'custom_query' || type === 'project') {
this.contextValue = 'custom-query-';
Object.entries(data).forEach(entry => {
if (Array.isArray(entry[1])) {
this.contextValue += `${entry[0]}:${entry[1].join(',')};`;
} else {
this.contextValue += `${entry[0]}:${entry[1]};`;
}
});
if (type === 'project') {
this.contextValue += `project_uri:${uri};`;
}
} else {
this.command = {
command,
arguments: arg,
};
}
this.command = {
command,
arguments: arg,
};
}
this.iconPath = {
light: path.join(__dirname, iconPathLight),
......
......@@ -70,7 +70,7 @@ describe('GitLab tree view', () => {
}),
createQueryJsonEndpoint('/projects/278964/merge_requests', {
'?scope=assigned_to_me&state=opened': [openMergeRequestResponse],
'?scope=assigned_to_me&state=all&author_id=7237201&assignee_id=7237201&wip=yes&labels=frontend,backend&milestone=13.6&search=query&created_before=2020-10-11T03&created_after=2018-11-01T03&updated_before=2020-10-30T03&updated_after=2018-11-01T03&order_by=updated_at&sort=asc&per_page=30': [
'?scope=assigned_to_me&state=all&author_id=7237201&assignee_id=7237201&wip=yes&labels=frontend,backend&milestone=13.6&search=query&created_before=2020-10-11T03:45:40Z&created_after=2018-11-01T03:45:40Z&updated_before=2020-10-30T03:45:40Z&updated_after=2018-11-01T03:45:40Z&order_by=updated_at&sort=asc&per_page=30': [
{ ...openMergeRequestResponse, title: 'Custom Query MR' },
],
}),
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册