@rancher/shell 3.0.12-rc.1 → 3.0.12-rc.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/assets/images/providers/entraid-black.svg +4 -0
- package/assets/images/providers/entraid.svg +9 -0
- package/assets/images/vendor/entraid.svg +9 -0
- package/assets/styles/app.scss +0 -1
- package/assets/translations/en-us.yaml +19 -17
- package/assets/translations/zh-hans.yaml +4 -8
- package/chart/__tests__/S3.test.ts +10 -3
- package/components/CountBox.vue +20 -0
- package/components/CreateDriver.vue +0 -12
- package/components/DetailText.vue +12 -3
- package/components/SelectIconGrid.vue +5 -0
- package/components/__tests__/CountBox.test.ts +72 -0
- package/components/__tests__/DetailText.test.ts +113 -0
- package/components/fleet/FleetClusterTargets/index.vue +18 -1
- package/components/form/InputWithSelect.vue +18 -10
- package/components/form/KeyValue.vue +17 -1
- package/components/form/LabeledSelect.vue +82 -24
- package/components/form/Select.vue +73 -56
- package/components/form/ServiceNameSelect.vue +13 -11
- package/components/form/__tests__/KeyValue.test.ts +66 -0
- package/components/form/__tests__/NodeScheduling.test.ts +9 -0
- package/components/form/labeled-select-utils/useLabeledSelectPagination.ts +138 -0
- package/components/nav/Group.vue +7 -6
- package/components/nav/Header.vue +24 -3
- package/components/nav/NotificationCenter/Notification.vue +4 -1
- package/components/nav/NotificationCenter/NotificationHeader.vue +20 -8
- package/components/nav/NotificationCenter/__tests__/NotificationHeader.test.ts +80 -0
- package/components/nav/Type.vue +8 -7
- package/components/nav/WindowManager/index.vue +2 -1
- package/components/nav/WorkspaceSwitcher.vue +13 -0
- package/components/nav/__tests__/Group.test.ts +67 -0
- package/components/nav/__tests__/Header.test.ts +235 -0
- package/components/nav/__tests__/Type.test.ts +20 -3
- package/components/templates/default.vue +34 -4
- package/components/templates/home.vue +12 -25
- package/components/templates/plain.vue +13 -26
- package/composables/useLabeledFormElement.ts +10 -2
- package/composables/useLabeledSelect.ts +60 -0
- package/composables/useUserRetentionValidation.ts +1 -49
- package/config/cookies.js +0 -1
- package/config/labels-annotations.js +1 -0
- package/config/query-params.js +1 -0
- package/config/router/routes.js +0 -8
- package/core/__tests__/plugin-products.test.ts +616 -25
- package/core/plugin-products-base.ts +31 -14
- package/core/plugin-products-helpers.ts +5 -4
- package/core/plugin-types.ts +18 -3
- package/core/types.ts +3 -1
- package/detail/__tests__/management.cattle.io.fleetworkspace.test.ts +128 -0
- package/detail/management.cattle.io.fleetworkspace.vue +49 -0
- package/edit/__tests__/fleet.cattle.io.helmop.test.ts +9 -0
- package/edit/__tests__/kontainerDriver.test.ts +0 -13
- package/edit/__tests__/nodeDriver.test.ts +5 -11
- package/edit/__tests__/resources.cattle.io.restore.test.ts +9 -0
- package/edit/auditlog.cattle.io.auditpolicy/__tests__/__snapshots__/General.test.ts.snap +6 -0
- package/edit/auth/__tests__/oidc.test.ts +54 -0
- package/edit/auth/azuread.vue +1 -1
- package/edit/auth/oidc.vue +8 -0
- package/edit/kontainerDriver.vue +1 -2
- package/edit/nodeDriver.vue +0 -2
- package/edit/provisioning.cattle.io.cluster/AgentEnv.vue +1 -0
- package/edit/provisioning.cattle.io.cluster/__tests__/AgentEnv.test.ts +25 -0
- package/edit/provisioning.cattle.io.cluster/index.vue +70 -99
- package/initialize/App.vue +29 -2
- package/initialize/install-plugins.js +0 -2
- package/list/__tests__/management.cattle.io.feature.test.ts +105 -0
- package/list/catalog.cattle.io.app.vue +25 -5
- package/list/management.cattle.io.feature.vue +1 -1
- package/list/management.cattle.io.fleetworkspace.vue +8 -0
- package/machine-config/amazonec2.vue +1 -0
- package/mixins/chart.js +40 -9
- package/models/__tests__/catalog.cattle.io.app.test.ts +15 -1
- package/models/__tests__/catalog.cattle.io.clusterrepo.test.ts +84 -0
- package/models/__tests__/chart.test.ts +99 -6
- package/models/__tests__/management.cattle.io.feature.test.ts +131 -0
- package/models/__tests__/monitoring.coreos.com.alertmanagerconfig.test.ts +98 -0
- package/models/catalog.cattle.io.app.js +21 -17
- package/models/catalog.cattle.io.clusterrepo.js +39 -11
- package/models/chart.js +33 -19
- package/models/fleet-application.js +1 -1
- package/models/fleet.cattle.io.bundle.js +1 -1
- package/models/kontainerdriver.js +11 -0
- package/models/management.cattle.io.authconfig.js +5 -1
- package/models/management.cattle.io.cluster.js +0 -53
- package/models/management.cattle.io.feature.js +3 -3
- package/models/management.cattle.io.kontainerdriver.js +1 -26
- package/models/monitoring.coreos.com.alertmanagerconfig.js +31 -17
- package/models/nodedriver.js +7 -0
- package/package.json +13 -12
- package/pages/c/_cluster/apps/charts/__tests__/chart.test.ts +189 -0
- package/pages/c/_cluster/apps/charts/__tests__/index.test.ts +55 -0
- package/pages/c/_cluster/apps/charts/__tests__/install.test.ts +53 -0
- package/pages/c/_cluster/apps/charts/chart.vue +217 -33
- package/pages/c/_cluster/apps/charts/index.vue +2 -2
- package/pages/c/_cluster/apps/charts/install.vue +8 -3
- package/pages/c/_cluster/auth/user.retention/index.vue +55 -22
- package/pages/c/_cluster/manager/drivers/kontainerDriver/index.vue +5 -7
- package/pages/c/_cluster/uiplugins/PluginInfoPanel.vue +39 -2
- package/pages/c/_cluster/uiplugins/__tests__/PluginInfoPanel.test.ts +61 -0
- package/pages/c/_cluster/uiplugins/__tests__/index.test.ts +15 -10
- package/pages/c/_cluster/uiplugins/index.vue +23 -25
- package/rancher-components/Form/LabeledInput/LabeledInput.test.ts +205 -1
- package/rancher-components/Form/LabeledInput/LabeledInput.vue +82 -4
- package/rancher-components/Form/ToggleSwitch/ToggleSwitch.vue +1 -1
- package/scripts/test-plugins-build.sh +5 -2
- package/server/server-middleware.js +2 -2
- package/static/humans.txt +1 -0
- package/static/robots.txt +34 -0
- package/static/welcome-cow.svg +18 -0
- package/store/__tests__/catalog.test.ts +161 -11
- package/store/auth.js +0 -3
- package/store/catalog.js +60 -8
- package/types/shell/index.d.ts +26 -22
- package/utils/__tests__/git.test.ts +270 -0
- package/utils/__tests__/inactivity.test.ts +316 -0
- package/utils/__tests__/object.test.ts +77 -0
- package/utils/__tests__/time.test.ts +14 -1
- package/utils/__tests__/url.test.ts +246 -0
- package/utils/object.js +33 -2
- package/utils/time.ts +5 -0
- package/vue.config.js +0 -9
- package/assets/images/providers/azuread-black.svg +0 -22
- package/assets/images/providers/azuread.svg +0 -25
- package/assets/images/vendor/azuread.svg +0 -18
- package/assets/styles/fonts/_dots.scss +0 -18
- package/components/EmberPage.vue +0 -622
- package/components/EmberPageView.vue +0 -39
- package/components/form/labeled-select-utils/labeled-select-pagination.ts +0 -116
- package/mixins/labeled-form-element.ts +0 -225
- package/pages/c/_cluster/explorer/tools/pages/_page.vue +0 -28
- package/pages/c/_cluster/manager/pages/_page.vue +0 -22
- package/pages/c/_cluster/mcapps/pages/_page.vue +0 -22
- package/plugins/ember-cookie.js +0 -17
- package/utils/ember-page.js +0 -30
package/store/auth.js
CHANGED
|
@@ -3,7 +3,6 @@ import { MANAGEMENT, EXT } from '@shell/config/types';
|
|
|
3
3
|
import { addObjects, findBy, joinStringList } from '@shell/utils/array';
|
|
4
4
|
import { openAuthPopup, returnTo } from '@shell/utils/auth';
|
|
5
5
|
import { base64Encode } from '@shell/utils/crypto';
|
|
6
|
-
import { removeEmberPage } from '@shell/utils/ember-page';
|
|
7
6
|
import { randomStr } from '@shell/utils/string';
|
|
8
7
|
import { addParams, parse as parseUrl, removeParam } from '@shell/utils/url';
|
|
9
8
|
|
|
@@ -429,8 +428,6 @@ export const actions = {
|
|
|
429
428
|
},
|
|
430
429
|
|
|
431
430
|
uiLogout({ commit, dispatch }, options = {}) {
|
|
432
|
-
removeEmberPage();
|
|
433
|
-
|
|
434
431
|
commit('loggedOut');
|
|
435
432
|
dispatch('onLogout', options, { root: true });
|
|
436
433
|
|
package/store/catalog.js
CHANGED
|
@@ -325,8 +325,12 @@ export const actions = {
|
|
|
325
325
|
* force: Always refresh catalog's helm repo by re-fetching index.yaml
|
|
326
326
|
*
|
|
327
327
|
* reset: clear existing charts and version cache
|
|
328
|
+
*
|
|
329
|
+
* repoKeys: Optional array of specific repo keys (IDs) to refresh. When provided, only these specific
|
|
330
|
+
* repos will be fetched, and only their existing charts will be cleared from the cache to avoid
|
|
331
|
+
* duplicate chart entries or wiping out unrelated chart data.
|
|
328
332
|
*/
|
|
329
|
-
async load(ctx, { force, reset } = {}) {
|
|
333
|
+
async load(ctx, { force, reset, repoKeys = [] } = {}) {
|
|
330
334
|
const {
|
|
331
335
|
state, getters, rootGetters, commit, dispatch
|
|
332
336
|
} = ctx;
|
|
@@ -360,14 +364,34 @@ export const actions = {
|
|
|
360
364
|
promises = {};
|
|
361
365
|
|
|
362
366
|
for ( const repo of repos ) {
|
|
363
|
-
|
|
367
|
+
let shouldLoad = false;
|
|
368
|
+
|
|
369
|
+
if (repoKeys.length) {
|
|
370
|
+
// If repoKeys are explicitly provided (e.g. refreshing a single repo from the UI),
|
|
371
|
+
// we ONLY want to load the repos in that array. We intentionally ignore `!getters.isLoaded(repo)`
|
|
372
|
+
// here so we don't accidentally fetch other unrelated repos just because they haven't loaded yet.
|
|
373
|
+
shouldLoad = repoKeys.includes(repo._key);
|
|
374
|
+
} else {
|
|
375
|
+
// Default behavior: load if explicitly forced, OR if the repo hasn't been loaded into state yet.
|
|
376
|
+
shouldLoad = force === true || !getters.isLoaded(repo);
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
if ( shouldLoad && repo.canLoad ) {
|
|
364
380
|
console.info('Loading index for repo', repo.name, `(${ repo._key })`); // eslint-disable-line no-console
|
|
365
381
|
promises[repo._key] = repo.followLink('index');
|
|
366
382
|
}
|
|
367
383
|
}
|
|
368
384
|
|
|
369
385
|
const res = await allHashSettled(promises);
|
|
370
|
-
const charts = reset ? {} : state.charts;
|
|
386
|
+
const charts = reset ? {} : { ...state.charts };
|
|
387
|
+
let versionInfos = null;
|
|
388
|
+
|
|
389
|
+
if (reset) {
|
|
390
|
+
versionInfos = {};
|
|
391
|
+
} else if (repoKeys.length) {
|
|
392
|
+
versionInfos = { ...state.versionInfos };
|
|
393
|
+
}
|
|
394
|
+
|
|
371
395
|
const errors = [];
|
|
372
396
|
|
|
373
397
|
for ( const key of Object.keys(res) ) {
|
|
@@ -379,6 +403,28 @@ export const actions = {
|
|
|
379
403
|
continue;
|
|
380
404
|
}
|
|
381
405
|
|
|
406
|
+
// We are targeting specific repos. To prevent duplicate chart versions from appearing,
|
|
407
|
+
// we must remove the old charts for this specific repo before appending the newly fetched ones,
|
|
408
|
+
// but ONLY if the fetch was successful.
|
|
409
|
+
if (repoKeys.length && repoKeys.includes(key)) {
|
|
410
|
+
for (const chartKey in charts) {
|
|
411
|
+
if (charts[chartKey].repoKey === key) {
|
|
412
|
+
delete charts[chartKey];
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
// Also clear out cached version info for this repo so we don't display stale READMEs/values
|
|
417
|
+
const repoType = repo.type === CATALOG.CLUSTER_REPO ? 'cluster' : 'namespace';
|
|
418
|
+
const repoName = repo.metadata.name;
|
|
419
|
+
const versionPrefix = `${ repoType }/${ repoName }/`;
|
|
420
|
+
|
|
421
|
+
for (const versionKey in versionInfos) {
|
|
422
|
+
if (versionKey.startsWith(versionPrefix)) {
|
|
423
|
+
delete versionInfos[versionKey];
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
|
|
382
428
|
for ( const k in obj.value.entries ) {
|
|
383
429
|
for ( const entry of obj.value.entries[k] ) {
|
|
384
430
|
addChart(ctx, charts, entry, repo);
|
|
@@ -394,13 +440,17 @@ export const actions = {
|
|
|
394
440
|
loaded,
|
|
395
441
|
});
|
|
396
442
|
|
|
397
|
-
if (
|
|
398
|
-
commit('setVersions',
|
|
443
|
+
if (versionInfos) {
|
|
444
|
+
commit('setVersions', versionInfos);
|
|
399
445
|
}
|
|
400
446
|
},
|
|
401
447
|
|
|
448
|
+
/**
|
|
449
|
+
* Globally refreshes all loaded repositories by triggering their refresh actions concurrently,
|
|
450
|
+
* bypassing individual catalog loads, and then performs a single, global catalog/load.
|
|
451
|
+
*/
|
|
402
452
|
async refresh({ getters, commit, dispatch }) {
|
|
403
|
-
const promises = getters.repos.map((x) => x.refresh());
|
|
453
|
+
const promises = getters.repos.map((x) => x.refresh(false));
|
|
404
454
|
|
|
405
455
|
// @TODO wait for repo state to indicate they're done once the API has that
|
|
406
456
|
|
|
@@ -488,7 +538,9 @@ function addChart(ctx, map, chart, repo) {
|
|
|
488
538
|
certified = CATALOG_ANNOTATIONS._OTHER;
|
|
489
539
|
}
|
|
490
540
|
|
|
491
|
-
|
|
541
|
+
const isDeprecated = !!chart.deprecated || chart.annotations?.[CATALOG_ANNOTATIONS.DEPRECATED] === 'true';
|
|
542
|
+
|
|
543
|
+
if ( isDeprecated ) {
|
|
492
544
|
sideLabel = DEPRECATED;
|
|
493
545
|
} else if ( chart.annotations?.[CATALOG_ANNOTATIONS.EXPERIMENTAL] ) {
|
|
494
546
|
sideLabel = EXPERIMENTAL;
|
|
@@ -546,7 +598,7 @@ function addChart(ctx, map, chart, repo) {
|
|
|
546
598
|
versions: [],
|
|
547
599
|
keywords: chart.keywords || [],
|
|
548
600
|
categories: filterCategories(chart.keywords),
|
|
549
|
-
deprecated:
|
|
601
|
+
deprecated: isDeprecated,
|
|
550
602
|
primeOnly,
|
|
551
603
|
experimental,
|
|
552
604
|
hidden: !!chart.annotations?.[CATALOG_ANNOTATIONS.HIDDEN],
|
package/types/shell/index.d.ts
CHANGED
|
@@ -81,6 +81,7 @@ export namespace CATALOG {
|
|
|
81
81
|
let _OTHER: string;
|
|
82
82
|
let PRIME_ONLY: string;
|
|
83
83
|
let EXPERIMENTAL: string;
|
|
84
|
+
let DEPRECATED: string;
|
|
84
85
|
let NAMESPACE: string;
|
|
85
86
|
let RELEASE_NAME: string;
|
|
86
87
|
let FEATURED: string;
|
|
@@ -247,6 +248,7 @@ export namespace CATALOG {
|
|
|
247
248
|
let _OTHER: string;
|
|
248
249
|
let PRIME_ONLY: string;
|
|
249
250
|
let EXPERIMENTAL: string;
|
|
251
|
+
let DEPRECATED: string;
|
|
250
252
|
let NAMESPACE: string;
|
|
251
253
|
let RELEASE_NAME: string;
|
|
252
254
|
let FEATURED: string;
|
|
@@ -650,6 +652,7 @@ export const DEPRECATED: "deprecated";
|
|
|
650
652
|
export const HIDDEN: "hidden";
|
|
651
653
|
export const FROM_TOOLS: "tools";
|
|
652
654
|
export const FROM_CLUSTER: "cluster";
|
|
655
|
+
export const NEW_APP_INSTANCE: "new-instance";
|
|
653
656
|
export const HIDE_SIDE_NAV: "hide-side-nav";
|
|
654
657
|
export const PROVIDER: "provider";
|
|
655
658
|
export const CLOUD_CREDENTIAL: "cloud";
|
|
@@ -725,6 +728,7 @@ export const DEPRECATED: "deprecated";
|
|
|
725
728
|
export const HIDDEN: "hidden";
|
|
726
729
|
export const FROM_TOOLS: "tools";
|
|
727
730
|
export const FROM_CLUSTER: "cluster";
|
|
731
|
+
export const NEW_APP_INSTANCE: "new-instance";
|
|
728
732
|
export const HIDE_SIDE_NAV: "hide-side-nav";
|
|
729
733
|
export const PROVIDER: "provider";
|
|
730
734
|
export const CLOUD_CREDENTIAL: "cloud";
|
|
@@ -5745,7 +5749,17 @@ export default class ClusterRepo {
|
|
|
5745
5749
|
};
|
|
5746
5750
|
get _isClusterRepoDisabled(): boolean;
|
|
5747
5751
|
get _availableActions(): any;
|
|
5748
|
-
|
|
5752
|
+
/**
|
|
5753
|
+
* Refreshes the repository by updating its forceUpdate annotation and waiting for it to become active.
|
|
5754
|
+
* @param {boolean} dispatchLoad - Whether to dispatch the catalog/load action after refreshing. Defaults to true.
|
|
5755
|
+
*/
|
|
5756
|
+
refresh(dispatchLoad?: boolean): Promise<void>;
|
|
5757
|
+
/**
|
|
5758
|
+
* Performs a bulk refresh on multiple repositories concurrently, bypassing individual
|
|
5759
|
+
* catalog loads, and dispatches a single catalog/load for all repositories once they are active.
|
|
5760
|
+
* @param {ClusterRepo[]} items - Array of repository instances to refresh.
|
|
5761
|
+
*/
|
|
5762
|
+
refreshBulk(items: ClusterRepo[]): Promise<void>;
|
|
5749
5763
|
disableClusterRepo(): Promise<void>;
|
|
5750
5764
|
enableClusterRepo(): Promise<void>;
|
|
5751
5765
|
get isGit(): boolean;
|
|
@@ -5793,7 +5807,17 @@ export default class ClusterRepo {
|
|
|
5793
5807
|
};
|
|
5794
5808
|
get _isClusterRepoDisabled(): boolean;
|
|
5795
5809
|
get _availableActions(): any;
|
|
5796
|
-
|
|
5810
|
+
/**
|
|
5811
|
+
* Refreshes the repository by updating its forceUpdate annotation and waiting for it to become active.
|
|
5812
|
+
* @param {boolean} dispatchLoad - Whether to dispatch the catalog/load action after refreshing. Defaults to true.
|
|
5813
|
+
*/
|
|
5814
|
+
refresh(dispatchLoad?: boolean): Promise<void>;
|
|
5815
|
+
/**
|
|
5816
|
+
* Performs a bulk refresh on multiple repositories concurrently, bypassing individual
|
|
5817
|
+
* catalog loads, and dispatches a single catalog/load for all repositories once they are active.
|
|
5818
|
+
* @param {ClusterRepo[]} items - Array of repository instances to refresh.
|
|
5819
|
+
*/
|
|
5820
|
+
refreshBulk(items: ClusterRepo[]): Promise<void>;
|
|
5797
5821
|
disableClusterRepo(): Promise<void>;
|
|
5798
5822
|
enableClusterRepo(): Promise<void>;
|
|
5799
5823
|
get isGit(): boolean;
|
|
@@ -9213,26 +9237,6 @@ export function resolveMachineConfigComponent(key: any): string;
|
|
|
9213
9237
|
export function resolveCloudCredentialComponent(key: any): string;
|
|
9214
9238
|
}
|
|
9215
9239
|
|
|
9216
|
-
// @shell/utils/ember-page
|
|
9217
|
-
|
|
9218
|
-
declare module '@shell/utils/ember-page' {
|
|
9219
|
-
export function findEmberPage(): HTMLElement;
|
|
9220
|
-
export function clearEmberInactiveTimer(): void;
|
|
9221
|
-
export function startEmberInactiveTimer(): void;
|
|
9222
|
-
export function removeEmberPage(): void;
|
|
9223
|
-
export const EMBER_FRAME: "ember-iframe";
|
|
9224
|
-
}
|
|
9225
|
-
|
|
9226
|
-
// @shell/utils/ember-page.js
|
|
9227
|
-
|
|
9228
|
-
declare module '@shell/utils/ember-page.js' {
|
|
9229
|
-
export function findEmberPage(): HTMLElement;
|
|
9230
|
-
export function clearEmberInactiveTimer(): void;
|
|
9231
|
-
export function startEmberInactiveTimer(): void;
|
|
9232
|
-
export function removeEmberPage(): void;
|
|
9233
|
-
export const EMBER_FRAME: "ember-iframe";
|
|
9234
|
-
}
|
|
9235
|
-
|
|
9236
9240
|
// @shell/utils/error
|
|
9237
9241
|
|
|
9238
9242
|
declare module '@shell/utils/error' {
|
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
import { GitUtils, Commit } from '@shell/utils/git';
|
|
2
|
+
|
|
3
|
+
describe('git utils', () => {
|
|
4
|
+
describe('gitUtils.github.normalize.repo', () => {
|
|
5
|
+
it('maps owner fields from GitHub API response', () => {
|
|
6
|
+
const data = {
|
|
7
|
+
owner: {
|
|
8
|
+
login: 'octocat',
|
|
9
|
+
html_url: 'https://github.com/octocat',
|
|
10
|
+
avatar_url: 'https://avatars.githubusercontent.com/u/1?v=4'
|
|
11
|
+
},
|
|
12
|
+
description: 'Hello World',
|
|
13
|
+
created_at: '2021-01-01T00:00:00Z',
|
|
14
|
+
updated_at: '2021-06-01T00:00:00Z',
|
|
15
|
+
html_url: 'https://github.com/octocat/hello-world',
|
|
16
|
+
name: 'hello-world'
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
const result = GitUtils.github.normalize.repo(data);
|
|
20
|
+
|
|
21
|
+
expect(result.owner).toStrictEqual({
|
|
22
|
+
name: 'octocat',
|
|
23
|
+
htmlUrl: 'https://github.com/octocat',
|
|
24
|
+
avatarUrl: 'https://avatars.githubusercontent.com/u/1?v=4'
|
|
25
|
+
});
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
it('maps repo-level fields from GitHub API response', () => {
|
|
29
|
+
const data = {
|
|
30
|
+
owner: {
|
|
31
|
+
login: 'octocat', html_url: '', avatar_url: ''
|
|
32
|
+
},
|
|
33
|
+
description: 'A repository description',
|
|
34
|
+
created_at: '2021-01-01T00:00:00Z',
|
|
35
|
+
updated_at: '2022-03-15T12:00:00Z',
|
|
36
|
+
html_url: 'https://github.com/octocat/repo',
|
|
37
|
+
name: 'my-repo'
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
const result = GitUtils.github.normalize.repo(data);
|
|
41
|
+
|
|
42
|
+
expect(result.description).toStrictEqual('A repository description');
|
|
43
|
+
expect(result.created_at).toStrictEqual('2021-01-01T00:00:00Z');
|
|
44
|
+
expect(result.updated_at).toStrictEqual('2022-03-15T12:00:00Z');
|
|
45
|
+
expect(result.htmlUrl).toStrictEqual('https://github.com/octocat/repo');
|
|
46
|
+
expect(result.name).toStrictEqual('my-repo');
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
it('handles missing owner gracefully', () => {
|
|
50
|
+
const data = {
|
|
51
|
+
owner: undefined,
|
|
52
|
+
description: 'No owner',
|
|
53
|
+
created_at: '2021-01-01T00:00:00Z',
|
|
54
|
+
updated_at: '2021-01-01T00:00:00Z',
|
|
55
|
+
html_url: 'https://github.com/no/owner',
|
|
56
|
+
name: 'no-owner'
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
const result = GitUtils.github.normalize.repo(data);
|
|
60
|
+
|
|
61
|
+
expect(result.owner).toStrictEqual({
|
|
62
|
+
name: undefined,
|
|
63
|
+
htmlUrl: undefined,
|
|
64
|
+
avatarUrl: undefined
|
|
65
|
+
});
|
|
66
|
+
});
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
describe('gitUtils.github.normalize.commit', () => {
|
|
70
|
+
it('maps commit fields from GitHub API response', () => {
|
|
71
|
+
const data = {
|
|
72
|
+
commit: {
|
|
73
|
+
message: 'fix: resolve issue',
|
|
74
|
+
committer: { date: '2022-01-15T10:30:00Z' }
|
|
75
|
+
},
|
|
76
|
+
html_url: 'https://github.com/octocat/repo/commit/abc1234567890',
|
|
77
|
+
sha: 'abc1234567890abcdef',
|
|
78
|
+
author: {
|
|
79
|
+
login: 'octocat',
|
|
80
|
+
avatar_url: 'https://avatars.githubusercontent.com/u/1?v=4',
|
|
81
|
+
htmlUrl: 'https://github.com/octocat'
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
const result = GitUtils.github.normalize.commit(data);
|
|
86
|
+
|
|
87
|
+
expect(result.message).toStrictEqual('fix: resolve issue');
|
|
88
|
+
expect(result.htmlUrl).toStrictEqual('https://github.com/octocat/repo/commit/abc1234567890');
|
|
89
|
+
expect(result.sha).toStrictEqual('abc1234');
|
|
90
|
+
expect(result.commitId).toStrictEqual('abc1234567890abcdef');
|
|
91
|
+
expect(result.date).toStrictEqual('2022-01-15T10:30:00Z');
|
|
92
|
+
expect(result.isChecked).toStrictEqual(false);
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
it('truncates sha to 7 characters', () => {
|
|
96
|
+
const data = {
|
|
97
|
+
commit: { message: 'chore: update deps', committer: { date: '2022-01-01T00:00:00Z' } },
|
|
98
|
+
html_url: 'https://github.com/octocat/repo/commit/1234567890',
|
|
99
|
+
sha: '1234567890abcdef1234',
|
|
100
|
+
author: {
|
|
101
|
+
login: 'user', avatar_url: '', htmlUrl: ''
|
|
102
|
+
}
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
const result = GitUtils.github.normalize.commit(data);
|
|
106
|
+
|
|
107
|
+
expect(result.sha).toStrictEqual('1234567');
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
it('returns undefined sha when sha is empty string', () => {
|
|
111
|
+
const data = {
|
|
112
|
+
commit: { message: 'fix: bug', committer: { date: '2022-01-01T00:00:00Z' } },
|
|
113
|
+
html_url: 'https://github.com/octocat/repo/commit/x',
|
|
114
|
+
sha: '',
|
|
115
|
+
author: {
|
|
116
|
+
login: 'user', avatar_url: '', htmlUrl: ''
|
|
117
|
+
}
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
const result: Commit = GitUtils.github.normalize.commit(data);
|
|
121
|
+
|
|
122
|
+
expect(result.sha).toBeUndefined();
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
it('maps author fields from GitHub API response', () => {
|
|
126
|
+
const data = {
|
|
127
|
+
commit: { message: 'feat: new feature', committer: { date: '2022-01-01T00:00:00Z' } },
|
|
128
|
+
html_url: 'https://github.com/octocat/repo/commit/abc',
|
|
129
|
+
sha: 'abcdef1234567890',
|
|
130
|
+
author: {
|
|
131
|
+
login: 'contributor',
|
|
132
|
+
avatar_url: 'https://avatars.githubusercontent.com/u/2?v=4',
|
|
133
|
+
htmlUrl: 'https://github.com/contributor'
|
|
134
|
+
}
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
const result = GitUtils.github.normalize.commit(data);
|
|
138
|
+
|
|
139
|
+
expect(result.author).toStrictEqual({
|
|
140
|
+
name: 'contributor',
|
|
141
|
+
avatarUrl: 'https://avatars.githubusercontent.com/u/2?v=4',
|
|
142
|
+
htmlUrl: 'https://github.com/contributor'
|
|
143
|
+
});
|
|
144
|
+
});
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
describe('gitUtils.gitlab.normalize.repo', () => {
|
|
148
|
+
it('maps owner fields from GitLab API response', () => {
|
|
149
|
+
const data = {
|
|
150
|
+
namespace: {
|
|
151
|
+
name: 'my-group',
|
|
152
|
+
web_url: 'https://gitlab.com/my-group',
|
|
153
|
+
avatar_url: 'https://gitlab.com/uploads/group.png'
|
|
154
|
+
},
|
|
155
|
+
description: 'GitLab repo description',
|
|
156
|
+
created_at: '2021-02-01T00:00:00Z',
|
|
157
|
+
last_activity_at: '2022-07-20T00:00:00Z',
|
|
158
|
+
web_url: 'https://gitlab.com/my-group/project',
|
|
159
|
+
name: 'project'
|
|
160
|
+
};
|
|
161
|
+
|
|
162
|
+
const result = GitUtils.gitlab.normalize.repo(data);
|
|
163
|
+
|
|
164
|
+
expect(result.owner).toStrictEqual({
|
|
165
|
+
name: 'my-group',
|
|
166
|
+
htmlUrl: 'https://gitlab.com/my-group',
|
|
167
|
+
avatarUrl: 'https://gitlab.com/uploads/group.png'
|
|
168
|
+
});
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
it('maps repo-level fields from GitLab API response', () => {
|
|
172
|
+
const data = {
|
|
173
|
+
namespace: {
|
|
174
|
+
name: 'ns', web_url: '', avatar_url: ''
|
|
175
|
+
},
|
|
176
|
+
description: 'My GitLab project',
|
|
177
|
+
created_at: '2020-05-01T00:00:00Z',
|
|
178
|
+
last_activity_at: '2023-01-10T00:00:00Z',
|
|
179
|
+
web_url: 'https://gitlab.com/ns/myproject',
|
|
180
|
+
name: 'myproject'
|
|
181
|
+
};
|
|
182
|
+
|
|
183
|
+
const result = GitUtils.gitlab.normalize.repo(data);
|
|
184
|
+
|
|
185
|
+
expect(result.description).toStrictEqual('My GitLab project');
|
|
186
|
+
expect(result.created_at).toStrictEqual('2020-05-01T00:00:00Z');
|
|
187
|
+
expect(result.updated_at).toStrictEqual('2023-01-10T00:00:00Z');
|
|
188
|
+
expect(result.htmlUrl).toStrictEqual('https://gitlab.com/ns/myproject');
|
|
189
|
+
expect(result.name).toStrictEqual('myproject');
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
it('maps updated_at from last_activity_at (not updated_at)', () => {
|
|
193
|
+
const data = {
|
|
194
|
+
namespace: {
|
|
195
|
+
name: 'ns', web_url: '', avatar_url: ''
|
|
196
|
+
},
|
|
197
|
+
description: '',
|
|
198
|
+
created_at: '2020-01-01T00:00:00Z',
|
|
199
|
+
last_activity_at: '2023-06-15T08:00:00Z',
|
|
200
|
+
updated_at: 'should-be-ignored',
|
|
201
|
+
web_url: 'https://gitlab.com/ns/proj',
|
|
202
|
+
name: 'proj'
|
|
203
|
+
};
|
|
204
|
+
|
|
205
|
+
const result = GitUtils.gitlab.normalize.repo(data);
|
|
206
|
+
|
|
207
|
+
expect(result.updated_at).toStrictEqual('2023-06-15T08:00:00Z');
|
|
208
|
+
});
|
|
209
|
+
});
|
|
210
|
+
|
|
211
|
+
describe('gitUtils.gitlab.normalize.commit', () => {
|
|
212
|
+
it('maps commit fields from GitLab API response', () => {
|
|
213
|
+
const data = {
|
|
214
|
+
message: 'refactor: clean up code',
|
|
215
|
+
web_url: 'https://gitlab.com/ns/proj/-/commit/abc1234',
|
|
216
|
+
short_id: 'abc1234',
|
|
217
|
+
id: 'abc1234567890abcdef',
|
|
218
|
+
author_name: 'Jane Doe',
|
|
219
|
+
avatar_url: 'https://gitlab.com/uploads/jane.png',
|
|
220
|
+
committed_date: '2022-03-10T14:00:00Z'
|
|
221
|
+
};
|
|
222
|
+
|
|
223
|
+
const result = GitUtils.gitlab.normalize.commit(data);
|
|
224
|
+
|
|
225
|
+
expect(result.message).toStrictEqual('refactor: clean up code');
|
|
226
|
+
expect(result.htmlUrl).toStrictEqual('https://gitlab.com/ns/proj/-/commit/abc1234');
|
|
227
|
+
expect(result.sha).toStrictEqual('abc1234');
|
|
228
|
+
expect(result.commitId).toStrictEqual('abc1234567890abcdef');
|
|
229
|
+
expect(result.date).toStrictEqual('2022-03-10T14:00:00Z');
|
|
230
|
+
expect(result.isChecked).toStrictEqual(false);
|
|
231
|
+
});
|
|
232
|
+
|
|
233
|
+
it('maps author fields from GitLab API response', () => {
|
|
234
|
+
const data = {
|
|
235
|
+
message: 'feat: add feature',
|
|
236
|
+
web_url: 'https://gitlab.com/ns/proj/-/commit/xyz',
|
|
237
|
+
short_id: 'xyz',
|
|
238
|
+
id: 'xyzabcdef',
|
|
239
|
+
author_name: 'John Smith',
|
|
240
|
+
avatar_url: 'https://gitlab.com/uploads/john.png',
|
|
241
|
+
committed_date: '2022-04-01T00:00:00Z'
|
|
242
|
+
};
|
|
243
|
+
|
|
244
|
+
const result = GitUtils.gitlab.normalize.commit(data);
|
|
245
|
+
|
|
246
|
+
expect(result.author).toStrictEqual({
|
|
247
|
+
name: 'John Smith',
|
|
248
|
+
avatarUrl: 'https://gitlab.com/uploads/john.png',
|
|
249
|
+
htmlUrl: 'https://gitlab.com/ns/proj/-/commit/xyz'
|
|
250
|
+
});
|
|
251
|
+
});
|
|
252
|
+
|
|
253
|
+
it('uses web_url for both htmlUrl and author.htmlUrl', () => {
|
|
254
|
+
const data = {
|
|
255
|
+
message: 'fix: something',
|
|
256
|
+
web_url: 'https://gitlab.com/ns/proj/-/commit/def456',
|
|
257
|
+
short_id: 'def456',
|
|
258
|
+
id: 'def456abc',
|
|
259
|
+
author_name: 'Dev',
|
|
260
|
+
avatar_url: '',
|
|
261
|
+
committed_date: '2022-01-01T00:00:00Z'
|
|
262
|
+
};
|
|
263
|
+
|
|
264
|
+
const result = GitUtils.gitlab.normalize.commit(data);
|
|
265
|
+
|
|
266
|
+
expect(result.htmlUrl).toStrictEqual('https://gitlab.com/ns/proj/-/commit/def456');
|
|
267
|
+
expect((result.author as any).htmlUrl).toStrictEqual('https://gitlab.com/ns/proj/-/commit/def456');
|
|
268
|
+
});
|
|
269
|
+
});
|
|
270
|
+
});
|