Skip to content

Commit 0d6e69e

Browse files
committed
Merge branch 'devel' into feature/AAP-70430-platform-help-menu-tests
Resolve conflicts: - PlatformAbout.tsx: keep useTranslation import and add SVG asset imports from devel - help-menu.spec.ts: keep trimmed test structure and add new test blocks from devel Made-with: Cursor
2 parents bda14a0 + 6e510d2 commit 0d6e69e

16 files changed

Lines changed: 731 additions & 256 deletions

.github/workflows/platform-pull-request.yml

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
name: Platform PR
22

33
on:
4+
push:
5+
branches: [main, devel]
46
pull_request:
57

68
env:
@@ -117,6 +119,8 @@ jobs:
117119
name: Vitest Coverage
118120
runs-on: ubuntu-latest
119121
timeout-minutes: 15
122+
permissions:
123+
id-token: write
120124
needs:
121125
- vitest-awx
122126
- vitest
@@ -157,8 +161,18 @@ jobs:
157161
path: coverage/combined
158162
retention-days: 7
159163
if-no-files-found: error
160-
- name: Upload unit test coverage to Codecov
161-
uses: codecov/codecov-action@v4
164+
- name: Upload unit test coverage to Codecov (OIDC)
165+
if: ${{ !vars.CODECOV_URL }}
166+
uses: codecov/codecov-action@v5
167+
with:
168+
use_oidc: true
169+
files: ./coverage/combined/lcov.info
170+
flags: unit-tests
171+
disable_search: true
172+
fail_ci_if_error: false
173+
- name: Upload unit test coverage to Codecov (Token)
174+
if: ${{ vars.CODECOV_URL }}
175+
uses: codecov/codecov-action@v5
162176
with:
163177
token: ${{ secrets.CODECOV_TOKEN }}
164178
url: ${{ vars.CODECOV_URL }}
@@ -168,8 +182,10 @@ jobs:
168182
disable_search: true
169183
fail_ci_if_error: false
170184
- name: Save off PR Number
185+
if: github.event_name == 'pull_request'
171186
run: echo "PR ${{ github.event.number }}" > pr_number.txt
172187
- name: Upload PR Number
188+
if: github.event_name == 'pull_request'
173189
uses: actions/upload-artifact@v4
174190
with:
175191
name: pr_number
@@ -221,7 +237,8 @@ jobs:
221237
path: coverage/combined
222238
continue-on-error: true
223239

224-
- name: SonarQube Scan
240+
- name: SonarQube Scan (PR)
241+
if: github.event_name == 'pull_request'
225242
uses: SonarSource/sonarqube-scan-action@v6
226243
env:
227244
SONAR_TOKEN: ${{ secrets[format('{0}', vars.SONAR_TOKEN_SECRET_NAME)] }}
@@ -234,6 +251,17 @@ jobs:
234251
-Dsonar.pullrequest.branch=${{ github.event.pull_request.head.ref }}
235252
-Dsonar.pullrequest.base=${{ github.event.pull_request.base.ref }}
236253
254+
- name: SonarQube Scan (Branch)
255+
if: github.event_name == 'push'
256+
uses: SonarSource/sonarqube-scan-action@v6
257+
env:
258+
SONAR_TOKEN: ${{ secrets[format('{0}', vars.SONAR_TOKEN_SECRET_NAME)] }}
259+
with:
260+
args: >
261+
-Dsonar.organization=${{ vars.SONAR_ORGANIZATION }}
262+
-Dsonar.projectKey=${{ vars.SONAR_PROJECT_KEY }}
263+
-Dsonar.branch.name=${{ github.ref_name }}
264+
237265
success:
238266
name: Success
239267
runs-on: ubuntu-latest

.tekton/aap-ui-hub-frontend-pull-request.yaml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
# Insights Hub PR pipeline - builds test image and runs E2E tests against CRC
12
apiVersion: tekton.dev/v1
23
kind: PipelineRun
34
metadata:
@@ -10,18 +11,18 @@ metadata:
1011
pipelinesascode.tekton.dev/max-keep-runs: '3'
1112
pipelinesascode.tekton.dev/on-cel-expression:
1213
event == "pull_request" && target_branch
13-
== "main" && ( "frontend/hub/***".pathChanged() || "frontend/common/***".pathChanged()
14+
== "devel" && ( "frontend/hub/***".pathChanged() || "frontend/common/***".pathChanged()
1415
|| "framework/***".pathChanged() || ".tekton/aap-ui-hub-frontend-pull-request.yaml".pathChanged()
1516
|| "build-tools/Dockerfile".pathChanged() || "package.json".pathChanged()
1617
|| "package-lock.json".pathChanged() || "playwright-insights/***".pathChanged() )
1718
pipelinesascode.tekton.dev/pipeline: https://raw.githubusercontent.com/RedHatInsights/konflux-pipelines/refs/heads/main/pipelines/platform-ui/docker-build-run-all-tests.yaml
19+
pipelinesascode.tekton.dev/target-namespace: ansible-automationhu-tenant
1820
creationTimestamp: null
1921
labels:
2022
appstudio.openshift.io/application: automation-hub-main
2123
appstudio.openshift.io/component: aap-ui-hub-frontend
2224
pipelines.appstudio.openshift.io/type: build
2325
name: aap-ui-hub-frontend-on-pull-request
24-
namespace: ansible-automationhu-tenant
2526
spec:
2627
params:
2728
- name: git-url

.tekton/aap-ui-hub-frontend-push.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,17 +9,17 @@ metadata:
99
pipelinesascode.tekton.dev/max-keep-runs: '3'
1010
pipelinesascode.tekton.dev/on-cel-expression:
1111
event == "push" && target_branch
12-
== "main" && ( "frontend/hub/***".pathChanged() || "frontend/common/***".pathChanged()
12+
== "devel" && ( "frontend/hub/***".pathChanged() || "frontend/common/***".pathChanged()
1313
|| "framework/***".pathChanged() || ".tekton/aap-ui-hub-frontend-push.yaml".pathChanged()
1414
|| "build-tools/Dockerfile".pathChanged() || "package.json".pathChanged()
1515
|| "package-lock.json".pathChanged() )
16+
pipelinesascode.tekton.dev/target-namespace: ansible-automationhu-tenant
1617
creationTimestamp: null
1718
labels:
1819
appstudio.openshift.io/application: automation-hub-main
1920
appstudio.openshift.io/component: aap-ui-hub-frontend
2021
pipelines.appstudio.openshift.io/type: build
2122
name: aap-ui-hub-frontend-on-push
22-
namespace: ansible-automationhu-tenant
2323
spec:
2424
params:
2525
- name: git-url

frontend/hub/collections/CollectionPage/CollectionContents.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ export function CollectionContents() {
3232
collection.collection_version?.name || ''
3333
}&namespace=${collection.collection_version?.namespace || ''}&version=${
3434
collection.collection_version?.version || ''
35-
}`
35+
}&exclude_fields=files,manifest,docs_blob`
3636
);
3737

3838
const tableColumns = useTableColumns(collection);

frontend/hub/collections/CollectionPage/CollectionDocumentation.test.tsx

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,39 @@ describe('CollectionDocumentation', () => {
123123
afterAll(() => server.close());
124124
afterEach(() => server.resetHandlers());
125125

126+
test('should request docs_blob by including exclude_fields in API URL', async () => {
127+
let capturedUrl = '';
128+
server.use(
129+
http.get(
130+
({ request }) => {
131+
return request.url.includes('/content/ansible/collection_versions/');
132+
},
133+
({ request }) => {
134+
capturedUrl = request.url;
135+
return HttpResponse.json(mockDocumentationResponse);
136+
}
137+
)
138+
);
139+
140+
render(
141+
<TestWrapper>
142+
<CollectionDocumentation />
143+
</TestWrapper>
144+
);
145+
146+
await waitFor(() => {
147+
expect(capturedUrl).toContain('exclude_fields=');
148+
});
149+
150+
const url = new URL(capturedUrl);
151+
const excludeFields = url.searchParams.get('exclude_fields');
152+
expect(excludeFields).toBeTruthy();
153+
expect(excludeFields).toContain('files');
154+
expect(excludeFields).toContain('manifest');
155+
expect(excludeFields).toContain('contents');
156+
expect(excludeFields).not.toContain('docs_blob');
157+
});
158+
126159
test('should render documentation tab with readme content', async () => {
127160
render(
128161
<TestWrapper>

frontend/hub/collections/CollectionPage/CollectionDocumentation.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ export function CollectionDocumentation() {
4545
collection?.collection_version?.namespace || ''
4646
}&name=${collection?.collection_version?.name || ''}&version=${
4747
collection?.collection_version?.version || ''
48-
}&offset=0&limit=1`
48+
}&offset=0&limit=1&exclude_fields=files,manifest,contents`
4949
);
5050

5151
// create groups for left tab of contents menu

frontend/hub/collections/CollectionPage/CollectionInstall.test.tsx

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,70 @@ describe('CollectionInstall', () => {
126126
afterAll(() => server.close());
127127
afterEach(() => server.resetHandlers());
128128

129+
test('should request docs_blob by including exclude_fields in API URL', async () => {
130+
let capturedUrl = '';
131+
server.use(
132+
http.get(
133+
({ request }) => {
134+
return request.url.includes('/content/ansible/collection_versions/');
135+
},
136+
({ request }) => {
137+
capturedUrl = request.url;
138+
return HttpResponse.json(mockContentResponse);
139+
}
140+
)
141+
);
142+
143+
render(
144+
<TestWrapper>
145+
<CollectionInstall />
146+
</TestWrapper>
147+
);
148+
149+
await waitFor(() => {
150+
expect(capturedUrl).toContain('exclude_fields=');
151+
});
152+
153+
const url = new URL(capturedUrl);
154+
const excludeFields = url.searchParams.get('exclude_fields');
155+
expect(excludeFields).toBeTruthy();
156+
expect(excludeFields).toContain('files');
157+
expect(excludeFields).toContain('manifest');
158+
expect(excludeFields).toContain('contents');
159+
expect(excludeFields).not.toContain('docs_blob');
160+
});
161+
162+
test('should handle missing docs_blob gracefully', async () => {
163+
server.use(
164+
http.get(
165+
({ request }) => request.url.includes('/content/ansible/collection_versions/'),
166+
() =>
167+
HttpResponse.json({
168+
count: 1,
169+
next: '',
170+
previous: '',
171+
results: [
172+
{
173+
license: ['MIT'],
174+
},
175+
],
176+
})
177+
)
178+
);
179+
180+
render(
181+
<TestWrapper>
182+
<CollectionInstall />
183+
</TestWrapper>
184+
);
185+
186+
await waitFor(() => {
187+
expect(screen.getByRole('heading', { name: 'Install' })).toBeInTheDocument();
188+
});
189+
190+
expect(screen.queryByRole('link', { name: /go to documentation/i })).not.toBeInTheDocument();
191+
});
192+
129193
test('should render install information with license', async () => {
130194
render(
131195
<TestWrapper>

frontend/hub/collections/CollectionPage/CollectionInstall.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ export function CollectionInstall() {
4141
collection?.collection_version?.namespace || ''
4242
}&name=${collection?.collection_version?.name || ''}&version=${
4343
collection?.collection_version?.version || ''
44-
}&offset=0&limit=1`
44+
}&offset=0&limit=1&exclude_fields=files,manifest,contents`
4545
);
4646

4747
const content = contentResults?.results[0];

frontend/hub/collections/CollectionPage/CollectionPage.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ export function CollectionPage() {
6868
collection?.collection_version?.namespace || ''
6969
}&name=${collection?.collection_version?.name || ''}&version=${
7070
collection?.collection_version?.version || ''
71-
}&offset=0&limit=1`
71+
}&offset=0&limit=1&exclude_fields=files,manifest,docs_blob,contents`
7272
: ''
7373
);
7474
const content = contentResults?.results?.[0];

frontend/hub/common/components/InsightsSelectGroup.test.tsx

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import userEvent from '@testing-library/user-event';
33
import { http, HttpResponse } from 'msw';
44
import { setupServer } from 'msw/node';
55
import { MemoryRouter } from 'react-router-dom';
6+
import { SWRConfig } from 'swr';
67
import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, it, vi } from 'vitest';
78
import { InsightsSelectGroup } from './InsightsSelectGroup';
89

@@ -52,9 +53,12 @@ describe('InsightsSelectGroup', () => {
5253

5354
const renderComponent = (props = {}) => {
5455
return render(
55-
<MemoryRouter>
56-
<InsightsSelectGroup {...defaultProps} {...props} />
57-
</MemoryRouter>
56+
// Fresh SWRConfig per test prevents cache from previous tests polluting responses
57+
<SWRConfig value={{ provider: () => new Map() }}>
58+
<MemoryRouter>
59+
<InsightsSelectGroup {...defaultProps} {...props} />
60+
</MemoryRouter>
61+
</SWRConfig>
5862
);
5963
};
6064

@@ -142,23 +146,23 @@ describe('InsightsSelectGroup', () => {
142146

143147
renderComponent({ assignedGroups: [{ name: 'admins' }] });
144148

145-
// Wait for data to load and filtering to complete
149+
// Wait for data to load, filtering to complete, and empty state to appear.
150+
// All assertions must be inside waitFor so retries continue until the
151+
// empty state renders — checking outside would race against the loading state.
146152
await waitFor(
147153
() => {
148-
// Verify that 'admins' is not in the table (filtered out)
149154
const cells = screen.queryAllByRole('cell');
150155
const adminsCell = cells.find((cell) => cell.textContent === 'admins');
151156
expect(adminsCell).toBeUndefined();
157+
158+
const emptyStateTitle = screen.queryByText('No groups found');
159+
const emptyStateDescription = screen.queryByText(
160+
'No groups match the current filter criteria.'
161+
);
162+
expect(emptyStateTitle || emptyStateDescription).toBeTruthy();
152163
},
153164
{ timeout: 5000 }
154165
);
155-
156-
// Verify empty state message appears (either title or description)
157-
const emptyStateTitle = screen.queryByText('No groups found');
158-
const emptyStateDescription = screen.queryByText(
159-
'No groups match the current filter criteria.'
160-
);
161-
expect(emptyStateTitle || emptyStateDescription).toBeTruthy();
162166
});
163167
});
164168

0 commit comments

Comments
 (0)