import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:jihu_gitlab_app/core/dependency_injector.dart'; import 'package:jihu_gitlab_app/core/local_storage.dart'; import 'package:jihu_gitlab_app/core/net/http_client.dart'; import 'package:jihu_gitlab_app/core/net/response.dart'; import 'package:jihu_gitlab_app/core/token_provider.dart'; import 'package:jihu_gitlab_app/core/user_provider.dart'; import 'package:jihu_gitlab_app/modules/issues/description_selector.dart'; import 'package:jihu_gitlab_app/modules/issues/issue_creation_page.dart'; import 'package:jihu_gitlab_app/modules/projects/group_details/group_and_project.dart'; import 'package:jihu_gitlab_app/modules/projects/group_details/subgroups/subgroup_list_model.dart'; import 'package:jihu_gitlab_app/modules/projects/groups/group_provider.dart'; import 'package:jihu_gitlab_app/modules/projects/groups/projects_groups_page.dart'; import 'package:jihu_gitlab_app/modules/projects/projects.dart'; import 'package:mockito/annotations.dart'; import 'package:mockito/mockito.dart'; import 'package:provider/provider.dart'; import 'package:shared_preferences/shared_preferences.dart'; import '../core/net/http_request_test.mocks.dart'; import '../mocker/tester.dart'; import 'create_issue_in_sub_group_test.mocks.dart'; final client = MockHttpClient(); @GenerateNiceMocks([MockSpec<GroupProvider>()]) void main() { var projectsModel = ProjectsModel(); var subgroupListModel = SubgroupListModel(); locator.registerSingleton(subgroupListModel); locator.registerSingleton(projectsModel); var provider = MockGroupProvider(); when(provider.loadFromLocal()).thenAnswer((_) => Future(() => [GroupAndProject(null, 118014, "highsoft", SubgroupItemType.group, "highsof-t", 0, false)])); projectsModel.injectDataProviderForTesting(provider); testWidgets('Should sub group page can create issue', (WidgetTester tester) async { SharedPreferences.setMockInitialValues(<String, Object>{}); await LocalStorage.init(); await TokenProvider().reset(Tester.token()); UserProvider().reset(Tester.user()); HttpClient.setInstance(client); when(client.get<List<dynamic>>('/api/v4/groups/1?all_available=true&page=1&per_page=50')).thenAnswer((_) => Future(() => Response.of<List<dynamic>>([]))); when(client.get<List<dynamic>>('/api/v4/groups/1/subgroups?all_available=true&page=1&per_page=50')).thenAnswer((_) => Future(() => Response.of<List<dynamic>>([]))); when(client.get<List<dynamic>>('/api/v4/groups/?top_level_only=true&page=1&per_page=50')).thenAnswer((_) => Future(() => Response.of<List<dynamic>>([]))); TokenProvider().reset(Tester.token()); UserProvider().reset(Tester.user()); when(client.get<Map<String, dynamic>>("/api/v4/user")).thenAnswer((_) => Future(() => Response.of<Map<String, dynamic>>({'id': 5882}))); HttpClient.setInstance(client); await tester.pumpWidget(MultiProvider( providers: [ChangeNotifierProvider(create: (context) => TokenProvider()), ChangeNotifierProvider(create: (context) => UserProvider())], child: MaterialApp(routes: { SubgroupPage.routeName: (context) => const SubgroupPage(arguments: {"name": "name1", "groupId": 1, "relativePath": "highsof-t"}) }, home: const Scaffold(body: ProjectsGroupsPage())))); // 用户点击进入sub group页面 await tester.pumpAndSettle(); await tester.tap(find.text(groups[0]['name'])); await tester.pumpAndSettle(); expect(find.byType(SubgroupPage), findsOneWidget); // 用户创建issue,选择project (展示并加载project列表) await tester.tap(find.byIcon(Icons.add_box_outlined)); await tester.pumpAndSettle(const Duration(seconds: 1)); expect(find.text('Select project'), findsOneWidget); expect(find.text('Go Demo'), findsOneWidget); expect(find.text('感知上次流水线的运行结果'), findsOneWidget); // 用户选择了一个project,进入创建页面 await tester.tap(find.text('Go Demo')); await tester.pumpAndSettle(); expect(find.byType(IssueCreationPage), findsOneWidget); expect(find.text('Create'), findsOneWidget); expect(find.text('Title (required)'), findsOneWidget); // 用户填入了一些信息 await tester.enterText( find.byWidgetPredicate( (widget) => widget is TextField && widget.decoration?.hintText == 'Write a issue title', ), 'Demo title'); await tester.enterText( find.byWidgetPredicate( (widget) => widget is TextField && widget.decoration?.hintText == 'Write a comment here...', ), 'Demo description'); // 用户点击了创建issue按钮 await tester.tap(find.text('Create')); await tester.pumpAndSettle(const Duration(seconds: 1)); // 创建成功,返回了上一个页面 expect(find.text('Issues'), findsOneWidget); UserProvider().fullReset(); TokenProvider().fullReset(); }); testWidgets('Should user create issue cancelled', (WidgetTester tester) async { HttpClient.setInstance(client); when(client.get<List<dynamic>>('/api/v4/groups/1?all_available=true&page=1&per_page=50')).thenAnswer((_) => Future(() => Response.of<List<dynamic>>([]))); when(client.get<List<dynamic>>('/api/v4/groups/1/subgroups?all_available=true&page=1&per_page=50')).thenAnswer((_) => Future(() => Response.of<List<dynamic>>([]))); when(client.get<List<dynamic>>('/api/v4/groups/?top_level_only=true&page=1&per_page=50')).thenAnswer((_) => Future(() => Response.of<List<dynamic>>([]))); TokenProvider().reset(Tester.token()); UserProvider().reset(Tester.user()); await tester.pumpWidget(MultiProvider( providers: [ChangeNotifierProvider(create: (context) => TokenProvider()), ChangeNotifierProvider(create: (context) => UserProvider())], child: MaterialApp(routes: { SubgroupPage.routeName: (context) => const SubgroupPage(arguments: {"name": "name1", "groupId": 1, "relativePath": "highsof-t"}) }, home: const Scaffold(body: ProjectsGroupsPage())))); // 用户点击进入sub group页面 await tester.pumpAndSettle(); await tester.tap(find.text(groups[0]['name'])); await tester.pumpAndSettle(); expect(find.byType(SubgroupPage), findsOneWidget); // 用户创建issue,选择project (展示并加载project列表) await tester.tap(find.byIcon(Icons.add_box_outlined)); await tester.pumpAndSettle(const Duration(seconds: 1)); expect(find.text('Select project'), findsOneWidget); expect(find.text('Go Demo'), findsOneWidget); expect(find.text('感知上次流水线的运行结果'), findsOneWidget); // 用户选择了一个project,进入创建页面 await tester.tap(find.text('Go Demo')); await tester.pumpAndSettle(); expect(find.byType(IssueCreationPage), findsOneWidget); expect(find.text('Create'), findsOneWidget); expect(find.text('Title (required)'), findsOneWidget); // 用户填入了一些信息 await tester.enterText( find.byWidgetPredicate( (widget) => widget is TextField && widget.decoration?.hintText == 'Write a issue title', ), 'Demo title'); // 用户点击取消 await tester.tap(find.byType(BackButton)); await tester.pumpAndSettle(const Duration(seconds: 1)); // 的确取消了 expect(find.byType(SubgroupPage), findsOneWidget); UserProvider().fullReset(); TokenProvider().fullReset(); }); group('Create issue select selector', () { testWidgets('Should user select description when creating issue', (WidgetTester tester) async { HttpClient.setInstance(client); TokenProvider().reset(Tester.token()); UserProvider().reset(Tester.user()); await tester.pumpWidget(MultiProvider( providers: [ChangeNotifierProvider(create: (context) => TokenProvider()), ChangeNotifierProvider(create: (context) => UserProvider())], child: MaterialApp(routes: { SubgroupPage.routeName: (context) => const SubgroupPage(arguments: {"name": "name1", "groupId": 1, "relativePath": "highsof-t"}), DescriptionSelector.routeName: (context, {arguments}) => const DescriptionSelector(arguments: {"projectId": 78632, 'free': false}) }, home: const Scaffold(body: ProjectsGroupsPage())))); // 用户点击进入sub group页面 await tester.pumpAndSettle(); await tester.tap(find.text(groups[0]['name'])); await tester.pumpAndSettle(); expect(find.byType(SubgroupPage), findsOneWidget); // 用户创建issue,选择project (展示并加载project列表) await tester.tap(find.byIcon(Icons.add_box_outlined)); await tester.pumpAndSettle(const Duration(seconds: 1)); expect(find.text('Select project'), findsOneWidget); expect(find.text('Go Demo'), findsOneWidget); expect(find.text('感知上次流水线的运行结果'), findsOneWidget); // 用户选择了一个project,进入创建页面 await tester.tap(find.text('Go Demo')); await tester.pumpAndSettle(); expect(find.byType(IssueCreationPage), findsOneWidget); expect(find.text('Create'), findsOneWidget); expect(find.text('Title (required)'), findsOneWidget); // 用户添加description的template await tester.tap(find.byKey(const Key("goto-description-selector"))); await tester.pumpAndSettle(); expect(find.text('feedback'), findsOneWidget); expect(find.text('o'), findsOneWidget); // 滑动后展示No More await tester.scrollUntilVisible(find.text('m'), 100.0); await tester.pumpAndSettle(); expect(find.text('m'), findsOneWidget); await tester.scrollUntilVisible(find.text('No more'), 100.0); expect(find.text('No more'), findsOneWidget); await tester.pumpAndSettle(); // 选择一个template await tester.tap(find.text('feedback')); await tester.pumpAndSettle(); expect(find.byType(IssueCreationPage), findsOneWidget); // 确实有个feedback回显在Description框中 expect(find.text('feedback'), findsOneWidget); expect(find.text('## yao'), findsOneWidget); UserProvider().fullReset(); TokenProvider().fullReset(); }); }); setUp(() async { SharedPreferences.setMockInitialValues(<String, Object>{}); await LocalStorage.init(); await TokenProvider().restore(); when(client.get<List<dynamic>>("/api/v4/groups?top_level_only=true&page=1&per_page=50")).thenAnswer((_) => Future(() => Response.of<List<dynamic>>(groups))); when(client.get<List<dynamic>>('/api/v4/groups/118014/subgroups?all_available=true&page=1&per_page=50')).thenAnswer((_) => Future(() => Response.of<List<dynamic>>(groups))); when(client.get<dynamic>('/api/v4/groups/118014?all_available=true&page=1&per_page=50')).thenAnswer((_) => Future(() => Response.of<dynamic>({'projects': []}))); when(client.get<List<dynamic>>('/api/v4/groups/1/subgroups?all_available=true&page=1&per_page=50')).thenAnswer((_) => Future(() => Response.of<List<dynamic>>([]))); when(client.get<dynamic>('/api/v4/groups/1?all_available=true&page=1&per_page=50')).thenAnswer((_) => Future(() => Response.of<dynamic>({'projects': []}))); when(client.post<List<dynamic>>("/api/graphql", [ { "operationName": "searchProjects", "variables": {"fullPath": "highsof-t", "search": ""}, "query": "query searchProjects(\$fullPath: ID!, \$search: String) {\n group(fullPath: \$fullPath) {\n id\n projects(search: \$search, includeSubgroups: true) {\n nodes {\n id\n issuesEnabled\n name\n nameWithNamespace\n webUrl\n __typename\n }\n __typename\n }\n __typename\n }\n}\n" } ])).thenAnswer((_) => Future(() { return Response.of<List<dynamic>>(projectList); })); when(client.get<List<dynamic>>('/api/v4/groups/1/issues?page=1&per_page=20')).thenAnswer((_) => Future(() { return Response.of<List<dynamic>>(projectList); })); when(client.post<Map<String, dynamic>>('/api/v4/projects/78632/issues', {'title': 'Demo title', 'description': 'Demo description', 'labels': ''})) .thenAnswer((_) => Future(() => Response.of<Map<String, dynamic>>({}))); when(client.get<List<dynamic>>('/api/v4/projects/78632/templates/issues?page=1&per_page=50')).thenAnswer((_) => Future(() => Response.of<List<dynamic>>([ {'key': 'feedback', 'name': 'feedback'}, {'key': 'o', 'name': 'o'} ]))); when(client.get<List<dynamic>>('/api/v4/projects/78632/templates/issues?page=2&per_page=50')).thenAnswer((_) => Future(() => Response.of<List<dynamic>>([ {'key': 'm', 'name': 'm'} ]))); when(client.get<List<dynamic>>('/api/v4/projects/78632/templates/issues?page=3&per_page=50')).thenAnswer((_) => Future(() => Response.of<List<dynamic>>([]))); when(client.get<Map<String, dynamic>>('/api/v4/projects/78632/templates/issues/feedback')) .thenAnswer((_) => Future(() => Response.of<Map<String, dynamic>>({'name': 'feedback', 'content': '## yao'}))); }); } var projectList = [ { "data": { "group": { "id": "gid://gitlab/Group/14276", "projects": { "nodes": [ { "id": "gid://gitlab/Project/78632", "issuesEnabled": true, "name": "Go Demo", "nameWithNamespace": "旗舰版演示 / Demo / Go Demo", "webUrl": "https://jihulab.com/ultimate-plan/demo/go-demo", "__typename": "Project" }, { "id": "gid://gitlab/Project/78218", "issuesEnabled": true, "name": "感知上次流水线的运行结果", "nameWithNamespace": "旗舰版演示 / 猫猫科技 / 感知上次流水线的运行结果", "webUrl": "https://jihulab.com/ultimate-plan/cat-tech/get-pre-ppl-status", "__typename": "Project" }, { "id": "gid://gitlab/Project/78155", "issuesEnabled": true, "name": "chatgpt", "nameWithNamespace": "旗舰版演示 / 猫猫科技 / 杂乱 / chatgpt", "webUrl": "https://jihulab.com/ultimate-plan/cat-tech/zaluan/chatgpt", "__typename": "Project" }, { "id": "gid://gitlab/Project/75468", "issuesEnabled": true, "name": "API", "nameWithNamespace": "旗舰版演示 / 极狐 GitLab App 产品线 / API", "webUrl": "https://jihulab.com/ultimate-plan/jihu-gitlab-app/api", "__typename": "Project" }, { "id": "gid://gitlab/Project/75045", "issuesEnabled": true, "name": "CI Next Build Number", "nameWithNamespace": "旗舰版演示 / scenarios / CI Next Build Number", "webUrl": "https://jihulab.com/ultimate-plan/scenarios/ci-next-build-number", "__typename": "Project" }, { "id": "gid://gitlab/Project/73806", "issuesEnabled": true, "name": "下游仓库", "nameWithNamespace": "旗舰版演示 / 猫猫科技 / 多项目流水线 / 下游仓库", "webUrl": "https://jihulab.com/ultimate-plan/cat-tech/multi-projects-pipeline/downstream", "__typename": "Project" }, { "id": "gid://gitlab/Project/73805", "issuesEnabled": true, "name": "上游仓库", "nameWithNamespace": "旗舰版演示 / 猫猫科技 / 多项目流水线 / 上游仓库", "webUrl": "https://jihulab.com/ultimate-plan/cat-tech/multi-projects-pipeline/upstream", "__typename": "Project" }, { "id": "gid://gitlab/Project/73764", "issuesEnabled": true, "name": "Secret Detection - Security policy project", "nameWithNamespace": "旗舰版演示 / 猫猫科技 / 安全扫描集合 Security Scanners / Secret Detection - Security policy project", "webUrl": "https://jihulab.com/ultimate-plan/cat-tech/security-scanners/secret-detection-security-policy-project", "__typename": "Project" }, { "id": "gid://gitlab/Project/72936", "issuesEnabled": true, "name": "demo mr test", "nameWithNamespace": "旗舰版演示 / 极狐 GitLab App 产品线 / demo mr test", "webUrl": "https://jihulab.com/ultimate-plan/jihu-gitlab-app/demo-mr-test", "__typename": "Project" }, { "id": "gid://gitlab/Project/71424", "issuesEnabled": true, "name": "Java 8 Maven Docker 代理加速", "nameWithNamespace": "旗舰版演示 / scenarios / Java 8 Maven Docker 代理加速", "webUrl": "https://jihulab.com/ultimate-plan/scenarios/java-8-maven-docker-proxy", "__typename": "Project" }, { "id": "gid://gitlab/Project/71183", "issuesEnabled": true, "name": "magic version", "nameWithNamespace": "旗舰版演示 / Demo / magic version", "webUrl": "https://jihulab.com/ultimate-plan/demo/magic-version", "__typename": "Project" }, { "id": "gid://gitlab/Project/70080", "issuesEnabled": true, "name": "demo vendor 3", "nameWithNamespace": "旗舰版演示 / 极狐 GitLab App 产品线 / demo vendor 3", "webUrl": "https://jihulab.com/ultimate-plan/jihu-gitlab-app/demo-vendor-3", "__typename": "Project" }, { "id": "gid://gitlab/Project/69920", "issuesEnabled": true, "name": "demo vendor 2", "nameWithNamespace": "旗舰版演示 / 极狐 GitLab App 产品线 / demo vendor 2", "webUrl": "https://jihulab.com/ultimate-plan/jihu-gitlab-app/demo-vendor-2", "__typename": "Project" }, { "id": "gid://gitlab/Project/69905", "issuesEnabled": true, "name": "CI templates", "nameWithNamespace": "旗舰版演示 / 极狐 GitLab App 产品线 / CI templates", "webUrl": "https://jihulab.com/ultimate-plan/jihu-gitlab-app/ci-templates", "__typename": "Project" }, { "id": "gid://gitlab/Project/69395", "issuesEnabled": true, "name": "demo vendor 1", "nameWithNamespace": "旗舰版演示 / 极狐 GitLab App 产品线 / demo vendor 1", "webUrl": "https://jihulab.com/ultimate-plan/jihu-gitlab-app/demo-vendor-1", "__typename": "Project" }, { "id": "gid://gitlab/Project/69355", "issuesEnabled": true, "name": "CI templates", "nameWithNamespace": "旗舰版演示 / CI templates", "webUrl": "https://jihulab.com/ultimate-plan/ci-templates", "__typename": "Project" }, { "id": "gid://gitlab/Project/68525", "issuesEnabled": true, "name": "Story", "nameWithNamespace": "旗舰版演示 / product Forum / Story", "webUrl": "https://jihulab.com/ultimate-plan/bbs/story", "__typename": "Project" }, { "id": "gid://gitlab/Project/68485", "issuesEnabled": true, "name": "Monorepo", "nameWithNamespace": "旗舰版演示 / scenarios / Monorepo", "webUrl": "https://jihulab.com/ultimate-plan/scenarios/monorepo", "__typename": "Project" }, { "id": "gid://gitlab/Project/68483", "issuesEnabled": true, "name": "phabricator tasks", "nameWithNamespace": "旗舰版演示 / Demo / phabricator tasks", "webUrl": "https://jihulab.com/ultimate-plan/demo/phabricator-tasks", "__typename": "Project" }, { "id": "gid://gitlab/Project/63364", "issuesEnabled": true, "name": "Hashicorp Vault 命令行方式集成CI", "nameWithNamespace": "旗舰版演示 / 猫猫科技 / Vault集成 / Hashicorp Vault 命令行方式集成CI", "webUrl": "https://jihulab.com/ultimate-plan/cat-tech/vault/hashicorp-vault", "__typename": "Project" }, { "id": "gid://gitlab/Project/62733", "issuesEnabled": true, "name": "DAST", "nameWithNamespace": "旗舰版演示 / 猫猫科技 / 安全扫描集合 Security Scanners / DAST", "webUrl": "https://jihulab.com/ultimate-plan/cat-tech/security-scanners/dast", "__typename": "Project" }, { "id": "gid://gitlab/Project/62732", "issuesEnabled": true, "name": "Container Scanning", "nameWithNamespace": "旗舰版演示 / 猫猫科技 / 安全扫描集合 Security Scanners / Container Scanning", "webUrl": "https://jihulab.com/ultimate-plan/cat-tech/security-scanners/container-scanning", "__typename": "Project" }, { "id": "gid://gitlab/Project/62730", "issuesEnabled": true, "name": "Infrastructure As Code Scanning", "nameWithNamespace": "旗舰版演示 / 猫猫科技 / 安全扫描集合 Security Scanners / Infrastructure As Code Scanning", "webUrl": "https://jihulab.com/ultimate-plan/cat-tech/security-scanners/infrastructure-as-code-scanning", "__typename": "Project" }, { "id": "gid://gitlab/Project/62728", "issuesEnabled": true, "name": "Secret Detection", "nameWithNamespace": "旗舰版演示 / 猫猫科技 / 安全扫描集合 Security Scanners / Secret Detection", "webUrl": "https://jihulab.com/ultimate-plan/cat-tech/security-scanners/secret-detection", "__typename": "Project" }, { "id": "gid://gitlab/Project/62725", "issuesEnabled": true, "name": "License Compliance", "nameWithNamespace": "旗舰版演示 / 猫猫科技 / 安全扫描集合 Security Scanners / License Compliance", "webUrl": "https://jihulab.com/ultimate-plan/cat-tech/security-scanners/license-compliance", "__typename": "Project" }, { "id": "gid://gitlab/Project/62721", "issuesEnabled": true, "name": "Dependency Scanning", "nameWithNamespace": "旗舰版演示 / 猫猫科技 / 安全扫描集合 Security Scanners / Dependency Scanning", "webUrl": "https://jihulab.com/ultimate-plan/cat-tech/security-scanners/dependency-scanning", "__typename": "Project" }, { "id": "gid://gitlab/Project/62720", "issuesEnabled": true, "name": "SAST", "nameWithNamespace": "旗舰版演示 / 猫猫科技 / 安全扫描集合 Security Scanners / SAST", "webUrl": "https://jihulab.com/ultimate-plan/cat-tech/security-scanners/sast", "__typename": "Project" }, { "id": "gid://gitlab/Project/59924", "issuesEnabled": true, "name": "app demo vendor 1", "nameWithNamespace": "旗舰版演示 / 极狐 GitLab App 产品线 / app demo vendor 1", "webUrl": "https://jihulab.com/ultimate-plan/jihu-gitlab-app/demo", "__typename": "Project" }, { "id": "gid://gitlab/Project/59893", "issuesEnabled": true, "name": "极狐 GitLab APP 代码", "nameWithNamespace": "旗舰版演示 / 极狐 GitLab App 产品线 / 极狐 GitLab APP 代码", "webUrl": "https://jihulab.com/ultimate-plan/jihu-gitlab-app/jihu-gitlab-app", "__typename": "Project" }, { "id": "gid://gitlab/Project/58063", "issuesEnabled": true, "name": "漏洞报告", "nameWithNamespace": "旗舰版演示 / features / 06安全管理 / 漏洞报告", "webUrl": "https://jihulab.com/ultimate-plan/features/06Secure/vulnerability-report", "__typename": "Project" }, { "id": "gid://gitlab/Project/56280", "issuesEnabled": true, "name": "HashiCorp Vault 专业版深度集", "nameWithNamespace": "旗舰版演示 / 猫猫科技 / Vault集成 / HashiCorp Vault 专业版深度集", "webUrl": "https://jihulab.com/ultimate-plan/cat-tech/vault/git-user-name-test", "__typename": "Project" }, { "id": "gid://gitlab/Project/54385", "issuesEnabled": true, "name": "WebGoat", "nameWithNamespace": "旗舰版演示 / Demo / WebGoat", "webUrl": "https://jihulab.com/ultimate-plan/demo/webgoat", "__typename": "Project" }, { "id": "gid://gitlab/Project/54357", "issuesEnabled": true, "name": "Java Sec Code", "nameWithNamespace": "旗舰版演示 / Demo / Java Sec Code", "webUrl": "https://jihulab.com/ultimate-plan/demo/java-sec-code", "__typename": "Project" }, { "id": "gid://gitlab/Project/53884", "issuesEnabled": true, "name": "部分发布", "nameWithNamespace": "旗舰版演示 / 猫猫科技 / 部分发布", "webUrl": "https://jihulab.com/ultimate-plan/cat-tech/partial-release-demo", "__typename": "Project" }, { "id": "gid://gitlab/Project/50641", "issuesEnabled": true, "name": "Java 17 Maven Demo", "nameWithNamespace": "旗舰版演示 / Demo / Java 17 Maven Demo", "webUrl": "https://jihulab.com/ultimate-plan/demo/java-17-maven-demo", "__typename": "Project" }, { "id": "gid://gitlab/Project/50430", "issuesEnabled": true, "name": "SAST-cpp", "nameWithNamespace": "旗舰版演示 / 猫猫科技 / 安全扫描集合 Security Scanners / SAST-cpp", "webUrl": "https://jihulab.com/ultimate-plan/cat-tech/security-scanners/sast-cpp", "__typename": "Project" }, { "id": "gid://gitlab/Project/49805", "issuesEnabled": true, "name": "Code Quality Demo Java", "nameWithNamespace": "旗舰版演示 / Demo / Code Quality Demo Java", "webUrl": "https://jihulab.com/ultimate-plan/demo/code-quality-demo-java", "__typename": "Project" }, { "id": "gid://gitlab/Project/45913", "issuesEnabled": true, "name": "C Demo", "nameWithNamespace": "旗舰版演示 / Demo / C Demo", "webUrl": "https://jihulab.com/ultimate-plan/demo/c-demo", "__typename": "Project" }, { "id": "gid://gitlab/Project/45095", "issuesEnabled": true, "name": "Java 8 Gradle", "nameWithNamespace": "旗舰版演示 / Demo / Java 8 Gradle", "webUrl": "https://jihulab.com/ultimate-plan/demo/java-8-gradle", "__typename": "Project" }, { "id": "gid://gitlab/Project/45025", "issuesEnabled": true, "name": "ONES 集成", "nameWithNamespace": "旗舰版演示 / Demo / ONES 集成", "webUrl": "https://jihulab.com/ultimate-plan/demo/ones", "__typename": "Project" }, { "id": "gid://gitlab/Project/45017", "issuesEnabled": true, "name": "PingCode 集成", "nameWithNamespace": "旗舰版演示 / Demo / PingCode 集成", "webUrl": "https://jihulab.com/ultimate-plan/demo/pingcode", "__typename": "Project" }, { "id": "gid://gitlab/Project/36019", "issuesEnabled": true, "name": "java ansible Demo", "nameWithNamespace": "旗舰版演示 / Demo / java ansible Demo", "webUrl": "https://jihulab.com/ultimate-plan/demo/java-ansible-demo", "__typename": "Project" }, { "id": "gid://gitlab/Project/34179", "issuesEnabled": true, "name": "Simply Simple Note", "nameWithNamespace": "旗舰版演示 / Demo / Simply Simple Note", "webUrl": "https://jihulab.com/ultimate-plan/demo/simply-simple-note", "__typename": "Project" }, { "id": "gid://gitlab/Project/34024", "issuesEnabled": true, "name": "docker ansible Demo", "nameWithNamespace": "旗舰版演示 / Demo / docker ansible Demo", "webUrl": "https://jihulab.com/ultimate-plan/demo/docker-ansible-demo", "__typename": "Project" }, { "id": "gid://gitlab/Project/32969", "issuesEnabled": true, "name": "License compliance Demo", "nameWithNamespace": "旗舰版演示 / Demo / License compliance Demo", "webUrl": "https://jihulab.com/ultimate-plan/demo/license-compliance-demo", "__typename": "Project" }, { "id": "gid://gitlab/Project/32875", "issuesEnabled": true, "name": "Infrastructure as Code Scanning Demo", "nameWithNamespace": "旗舰版演示 / Demo / Infrastructure as Code Scanning Demo", "webUrl": "https://jihulab.com/ultimate-plan/demo/infrastructure-as-code-scanning", "__typename": "Project" }, { "id": "gid://gitlab/Project/32867", "issuesEnabled": true, "name": "Container Scanning Demo", "nameWithNamespace": "旗舰版演示 / Demo / Container Scanning Demo", "webUrl": "https://jihulab.com/ultimate-plan/demo/container-scanning-demo", "__typename": "Project" }, { "id": "gid://gitlab/Project/32866", "issuesEnabled": true, "name": "Dependency Scanning Demo", "nameWithNamespace": "旗舰版演示 / Demo / Dependency Scanning Demo", "webUrl": "https://jihulab.com/ultimate-plan/demo/dependency-scanning-demo", "__typename": "Project" }, { "id": "gid://gitlab/Project/32599", "issuesEnabled": true, "name": "HTTP Archive", "nameWithNamespace": "旗舰版演示 / features / 06安全管理 / API Fuzzing / HTTP Archive", "webUrl": "https://jihulab.com/ultimate-plan/features/06Secure/api-fuzzing/http-archive", "__typename": "Project" }, { "id": "gid://gitlab/Project/32086", "issuesEnabled": true, "name": "OpenAPI v2 Specification", "nameWithNamespace": "旗舰版演示 / features / 06安全管理 / API Fuzzing / OpenAPI v2 Specification", "webUrl": "https://jihulab.com/ultimate-plan/features/06Secure/api-fuzzing/openapi-v2-specification", "__typename": "Project" }, { "id": "gid://gitlab/Project/30641", "issuesEnabled": true, "name": "项目申请", "nameWithNamespace": "旗舰版演示 / Demo / 项目申请", "webUrl": "https://jihulab.com/ultimate-plan/demo/create-project", "__typename": "Project" }, { "id": "gid://gitlab/Project/30364", "issuesEnabled": true, "name": "Demo Security policy", "nameWithNamespace": "旗舰版演示 / Demo / Demo Security policy", "webUrl": "https://jihulab.com/ultimate-plan/demo/sast-demo-security-policy-project", "__typename": "Project" }, { "id": "gid://gitlab/Project/30359", "issuesEnabled": true, "name": "DAST Demo", "nameWithNamespace": "旗舰版演示 / Demo / DAST Demo", "webUrl": "https://jihulab.com/ultimate-plan/demo/dast-demo", "__typename": "Project" }, { "id": "gid://gitlab/Project/30268", "issuesEnabled": true, "name": "Secret Detection Demo", "nameWithNamespace": "旗舰版演示 / Demo / Secret Detection Demo", "webUrl": "https://jihulab.com/ultimate-plan/demo/secret-detection-demo", "__typename": "Project" }, { "id": "gid://gitlab/Project/30089", "issuesEnabled": true, "name": "Build Docker images Demo ", "nameWithNamespace": "旗舰版演示 / Demo / Build Docker images Demo ", "webUrl": "https://jihulab.com/ultimate-plan/demo/build-docker-images-demo", "__typename": "Project" }, { "id": "gid://gitlab/Project/29092", "issuesEnabled": true, "name": "hello-jihu", "nameWithNamespace": "旗舰版演示 / Demo / hello-jihu", "webUrl": "https://jihulab.com/ultimate-plan/demo/hello-jihu", "__typename": "Project" }, { "id": "gid://gitlab/Project/29024", "issuesEnabled": true, "name": "hello-opensource", "nameWithNamespace": "旗舰版演示 / Demo / hello-opensource", "webUrl": "https://jihulab.com/ultimate-plan/demo/hello-opensource", "__typename": "Project" }, { "id": "gid://gitlab/Project/28919", "issuesEnabled": true, "name": "Java 8 Demo", "nameWithNamespace": "旗舰版演示 / Demo / Java 8 Demo", "webUrl": "https://jihulab.com/ultimate-plan/demo/java-8-demo", "__typename": "Project" }, { "id": "gid://gitlab/Project/28883", "issuesEnabled": true, "name": "SAST Demo", "nameWithNamespace": "旗舰版演示 / Demo / SAST Demo", "webUrl": "https://jihulab.com/ultimate-plan/demo/sast-demo", "__typename": "Project" }, { "id": "gid://gitlab/Project/27655", "issuesEnabled": true, "name": "vsm-demo-project", "nameWithNamespace": "旗舰版演示 / Demo / 价值流管理 / vsm-demo-project", "webUrl": "https://jihulab.com/ultimate-plan/demo/value-stream-mgmt/vsm-demo-project", "__typename": "Project" }, { "id": "gid://gitlab/Project/26535", "issuesEnabled": true, "name": "fuzzing-testing-demo", "nameWithNamespace": "旗舰版演示 / Demo / fuzzing-testing-demo", "webUrl": "https://jihulab.com/ultimate-plan/demo/fuzzing-testing-demo", "__typename": "Project" }, { "id": "gid://gitlab/Project/26250", "issuesEnabled": true, "name": "Jira Integration", "nameWithNamespace": "旗舰版演示 / Demo / Jira Integration", "webUrl": "https://jihulab.com/ultimate-plan/demo/jira-integration", "__typename": "Project" }, { "id": "gid://gitlab/Project/25773", "issuesEnabled": true, "name": "Vue Demo", "nameWithNamespace": "旗舰版演示 / Demo / Vue Demo", "webUrl": "https://jihulab.com/ultimate-plan/demo/vue-demo", "__typename": "Project" }, { "id": "gid://gitlab/Project/25199", "issuesEnabled": true, "name": "Laravel Demo", "nameWithNamespace": "旗舰版演示 / Demo / Laravel Demo", "webUrl": "https://jihulab.com/ultimate-plan/demo/laravel-demo", "__typename": "Project" }, { "id": "gid://gitlab/Project/23847", "issuesEnabled": true, "name": "主机部署", "nameWithNamespace": "旗舰版演示 / Demo / 主机部署", "webUrl": "https://jihulab.com/ultimate-plan/demo/cd-runner", "__typename": "Project" }, { "id": "gid://gitlab/Project/23204", "issuesEnabled": true, "name": "Vue Big Screen Plugin", "nameWithNamespace": "旗舰版演示 / Demo / Vue Big Screen Plugin", "webUrl": "https://jihulab.com/ultimate-plan/demo/vue-big-screen-plugin", "__typename": "Project" }, { "id": "gid://gitlab/Project/23194", "issuesEnabled": true, "name": "Vue Form Making", "nameWithNamespace": "旗舰版演示 / Demo / Vue Form Making", "webUrl": "https://jihulab.com/ultimate-plan/demo/vue-form-making", "__typename": "Project" }, { "id": "gid://gitlab/Project/19369", "issuesEnabled": true, "name": "config", "nameWithNamespace": "旗舰版演示 / product Forum / config", "webUrl": "https://jihulab.com/ultimate-plan/bbs/config", "__typename": "Project" }, { "id": "gid://gitlab/Project/17918", "issuesEnabled": true, "name": "Web", "nameWithNamespace": "旗舰版演示 / product Forum / Web", "webUrl": "https://jihulab.com/ultimate-plan/bbs/web", "__typename": "Project" }, { "id": "gid://gitlab/Project/17917", "issuesEnabled": true, "name": "API", "nameWithNamespace": "旗舰版演示 / product Forum / API", "webUrl": "https://jihulab.com/ultimate-plan/bbs/api", "__typename": "Project" } ], "__typename": "ProjectConnection" }, "__typename": "Group" } } } ]; List<dynamic> groups = [ { "id": 118014, "web_url": "https://jihulab.com/groups/highsof-t", "name": "highsoft", "path": "highsof-t", "description": "", "visibility": "private", "share_with_group_lock": false, "require_two_factor_authentication": false, "two_factor_grace_period": 48, "project_creation_level": "developer", "auto_devops_enabled": null, "subgroup_creation_level": "maintainer", "emails_disabled": null, "mentions_disabled": null, "lfs_enabled": true, "default_branch_protection": 2, "avatar_url": null, "request_access_enabled": true, "full_name": "highsoft", "full_path": "highsof-t", "created_at": "2022-11-09T15:54:15.587+08:00", "parent_id": null, "ldap_cn": null, "ldap_access": null }, { "id": 14269, "web_url": "https://jihulab.com/groups/free-plan", "name": "免费版演示", "path": "free-plan", "description": "", "visibility": "public", "share_with_group_lock": false, "require_two_factor_authentication": false, "two_factor_grace_period": 48, "project_creation_level": "developer", "auto_devops_enabled": null, "subgroup_creation_level": "maintainer", "emails_disabled": null, "mentions_disabled": null, "lfs_enabled": true, "default_branch_protection": 2, "avatar_url": null, "request_access_enabled": true, "full_name": "免费版演示", "full_path": "free-plan", "created_at": "2022-03-07T17:23:32.636+08:00", "parent_id": null, "ldap_cn": null, "ldap_access": null }, { "id": 14276, "web_url": "https://jihulab.com/groups/ultimate-plan", "name": "旗舰版演示", "path": "ultimate-plan", "description": "", "visibility": "public", "share_with_group_lock": false, "require_two_factor_authentication": false, "two_factor_grace_period": 48, "project_creation_level": "developer", "auto_devops_enabled": null, "subgroup_creation_level": "maintainer", "emails_disabled": null, "mentions_disabled": null, "lfs_enabled": true, "default_branch_protection": 2, "avatar_url": null, "request_access_enabled": true, "full_name": "旗舰版演示", "full_path": "ultimate-plan", "created_at": "2022-03-07T17:26:01.273+08:00", "parent_id": null, "ldap_cn": null, "ldap_access": null, "marked_for_deletion_on": null } ];