Skip to content

Commit

Permalink
Merge pull request #4446 from mendersoftware/master
Browse files Browse the repository at this point in the history
staging alignment
  • Loading branch information
mzedel committed Jun 10, 2024
2 parents ac3cef9 + 7bf5498 commit ac882ea
Show file tree
Hide file tree
Showing 11 changed files with 181 additions and 73 deletions.
3 changes: 2 additions & 1 deletion src/js/components/deployments/createdeployment.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ import DeltaIcon from '../../../assets/img/deltaicon.svg';
import { createDeployment, getDeploymentsConfig } from '../../actions/deploymentActions';
import { getGroupDevices } from '../../actions/deviceActions';
import { advanceOnboarding } from '../../actions/onboardingActions';
import { getReleases } from '../../actions/releaseActions';
import { getRelease, getReleases } from '../../actions/releaseActions';
import { ALL_DEVICES } from '../../constants/deviceConstants';
import { onboardingSteps } from '../../constants/onboardingConstants';
import { toggle, validatePhases } from '../../helpers';
Expand Down Expand Up @@ -149,6 +149,7 @@ export const CreateDeployment = props => {
const { devices = [], group, release } = deploymentObject;
if (release) {
dispatch(advanceOnboarding(onboardingSteps.SCHEDULING_ARTIFACT_SELECTION));
dispatch(getRelease(release.name));
}
dispatch(advanceOnboarding(onboardingSteps.SCHEDULING_GROUP_SELECTION));
let nextDeploymentObject = { deploymentDeviceCount: devices.length ? devices.length : 0 };
Expand Down
9 changes: 7 additions & 2 deletions src/js/components/deployments/deployments.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ import { Link, useNavigate } from 'react-router-dom';

import { Button, Tab, Tabs } from '@mui/material';

import { isUUID } from 'validator';

import { setSnackbar } from '../../actions/appActions';
import { abortDeployment, setDeploymentsState } from '../../actions/deploymentActions';
import { getDynamicGroups, getGroups } from '../../actions/deviceActions';
Expand Down Expand Up @@ -129,14 +131,17 @@ export const Deployments = () => {

const retryDeployment = (deployment, deploymentDeviceIds) => {
const { artifact_name, name, update_control_map = {} } = deployment;
const release = releases[artifact_name];
const release = releases[artifact_name] || { name: artifact_name };
const enterpriseSettings = isEnterprise
? {
phases: [{ batch_size: 100, start_ts: undefined, delay: 0 }],
update_control_map: { states: update_control_map.states || {} }
}
: {};
const targetDevicesConfig = name === ALL_DEVICES || groupsById[name] ? { group: name } : { devices: [devicesById[name]] };
const targetDevicesConfig =
name === ALL_DEVICES || groupsById[name]
? { group: name }
: { devices: isUUID(name) ? [devicesById[name]] : deploymentDeviceIds.map(id => devicesById[id] ?? { id }) };
const deploymentObject = {
deploymentDeviceIds,
release,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -935,10 +935,9 @@ label+.emotion-16 {
class="MuiFormControl-root emotion-4"
>
<label
class="MuiFormLabel-root MuiInputLabel-root MuiInputLabel-formControl MuiInputLabel-animated MuiInputLabel-sizeMedium MuiInputLabel-standard MuiFormLabel-colorPrimary MuiInputLabel-root MuiInputLabel-formControl MuiInputLabel-animated MuiInputLabel-sizeMedium MuiInputLabel-standard emotion-5"
class="MuiFormLabel-root MuiInputLabel-root MuiInputLabel-formControl MuiInputLabel-animated MuiInputLabel-sizeMedium MuiInputLabel-standard MuiFormLabel-colorPrimary MuiInputLabel-root MuiInputLabel-formControl MuiInputLabel-animated MuiInputLabel-sizeMedium MuiInputLabel-standard flexbox center-aligned emotion-5"
data-shrink="false"
for="release-name"
style="align-items: center; display: flex;"
>
Release name
<div
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ export const ArtifactInformation = ({ creation = {}, deviceTypes = [], onRemove,
/>
<h4>Artifact information</h4>
<FormControl>
<InputLabel htmlFor="release-name" style={{ alignItems: 'center', display: 'flex' }}>
<InputLabel htmlFor="release-name" className="flexbox center-aligned" onClick={e => e.preventDefault()}>
Release name
<InfoHintContainer>
<MenderHelpTooltip id={HELPTOOLTIPS.releaseName.id} />
Expand Down
5 changes: 3 additions & 2 deletions src/js/components/releases/releasedetails.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ import { removeArtifact, removeRelease, selectRelease, setReleaseTags, updateRel
import { DEPLOYMENT_ROUTES } from '../../constants/deploymentConstants';
import { FileSize, customSort, formatTime, toggle } from '../../helpers';
import { getReleaseListState, getReleaseTags, getSelectedRelease, getUserCapabilities } from '../../selectors';
import { generateReleasesPath } from '../../utils/locationutils';
import useWindowSize from '../../utils/resizehook';
import ChipSelect from '../common/chipselect';
import { ConfirmationButtons, EditButton } from '../common/confirm';
Expand Down Expand Up @@ -396,8 +397,8 @@ export const ReleaseDetails = () => {
const onRemoveArtifact = artifact => dispatch(removeArtifact(artifact.id)).finally(() => setShowRemoveArtifactDialog(false));

const copyLinkToClipboard = () => {
const location = window.location.href.substring(0, window.location.href.indexOf('/releases') + '/releases'.length);
copy(`${location}/${releaseName}`);
const location = window.location.href.substring(0, window.location.href.indexOf('/releases'));
copy(`${location}${generateReleasesPath({ pageState: { selectedRelease: releaseName } })}`);
dispatch(setSnackbar('Link copied to clipboard'));
};

Expand Down
5 changes: 3 additions & 2 deletions src/js/utils/locationutils.js
Original file line number Diff line number Diff line change
Expand Up @@ -396,14 +396,15 @@ export const formatReleases = ({ pageState: { searchTerm, selectedTags = [], tab
)
.join('&');

export const generateReleasesPath = ({ pageState: { selectedRelease } }) => `${releasesRoot}${selectedRelease ? `/${selectedRelease}` : ''}`;
export const generateReleasesPath = ({ pageState: { selectedRelease } }) =>
`${releasesRoot}${selectedRelease ? `/${encodeURIComponent(selectedRelease)}` : ''}`;

export const parseReleasesQuery = (queryParams, extraProps) => {
const name = queryParams.has('name') ? queryParams.get('name') : '';
const tab = queryParams.has('tab') ? queryParams.get('tab') : undefined;
const tags = queryParams.has('tag') ? queryParams.getAll('tag') : [];
const type = queryParams.has('type') ? queryParams.get('type') : '';
let selectedRelease = extraProps.location.pathname.substring(releasesRoot.length + 1);
let selectedRelease = decodeURIComponent(extraProps.location.pathname.substring(releasesRoot.length + 1));
if (!selectedRelease && extraProps.pageState.id?.length) {
selectedRelease = extraProps.pageState.id[0];
}
Expand Down
2 changes: 1 addition & 1 deletion tests/e2e_tests/integration/00-setup.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ test.describe('Test setup', () => {
const { token: JWT, userId } = await login(username, password, baseUrl);
const domain = baseUrlToDomain(baseUrl);
context = await prepareCookies(context, domain, userId);
context.addInitScript(token => {
await context.addInitScript(token => {
window.localStorage.setItem('JWT', JSON.stringify({ token }));
window.localStorage.setItem(`onboardingComplete`, 'true');
}, JWT);
Expand Down
42 changes: 29 additions & 13 deletions tests/e2e_tests/integration/03-files.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,28 +19,48 @@ import https from 'https';
import md5 from 'md5';

import test, { expect } from '../fixtures/fixtures';
import { selectors, storagePath, timeouts } from '../utils/constants';
import { getTokenFromStorage, tagRelease } from '../utils/commands';
import { releaseTag, selectors, storagePath, timeouts } from '../utils/constants';

dayjs.extend(isBetween);

const releaseTag = 'someTag';

test.describe('Files', () => {
const fileName = 'mender-demo-artifact.mender';
test.use({ storageState: storagePath });

test('allows file uploads', async ({ loggedInPage: page }) => {
test.beforeEach(async ({ loggedInPage: page }) => {
await page.click(`.leftNav :text('Releases')`);
// create an artifact to download first
await page.click(`button:has-text('Upload')`);
});

test('allows file uploads', async ({ loggedInPage: page }) => {
const uploadButton = await page.getByRole('button', { name: /upload/i });
await uploadButton.click();
await page.locator('.MuiDialog-paper .dropzone input').setInputFiles(`fixtures/${fileName}`);
await page.click(`.MuiDialog-paper button:has-text('Upload')`);
// give some extra time for the upload
await page.waitForTimeout(timeouts.fiveSeconds);
await page.waitForSelector('text=/last modified/i');
});

test('allows release notes manipulation', async ({ loggedInPage: page }) => {
test('allows artifact generation', async ({ baseUrl, loggedInPage: page }) => {
const releaseName = 'terminalImage';
const uploadButton = await page.getByRole('button', { name: /upload/i });
await uploadButton.click();
await page.locator('.MuiDialog-paper .dropzone input').setInputFiles(`fixtures/terminalContent.png`);
await page.getByPlaceholder(/installed-by-single-file/i).fill(`/usr/src`);
const deviceTypeInput = await page.getByLabel(/Release name/i);
await deviceTypeInput.clear();
await deviceTypeInput.fill(releaseName);
await page.getByLabel(/Device types/i).fill(`all-of-them,`);
await page.getByRole('button', { name: /next/i }).click();
await page.getByRole('button', { name: /upload artifact/i }).click();
await page.waitForSelector('text=1-2 of 2');
const token = await getTokenFromStorage(baseUrl);
await tagRelease(releaseName, 'customRelease', baseUrl, token);
await page.waitForTimeout(timeouts.oneSecond); // some extra time for the release to be tagged in the backend
await page.click(`.leftNav :text('Releases')`);
expect(await page.getByText(/customRelease/i)).toBeVisible();
});

test('allows release notes manipulation', async ({ loggedInPage: page }) => {
await page.getByText(/demo-artifact/i).click();
expect(await page.getByRole('heading', { name: /Release notes/i }).isVisible()).toBeTruthy();
const hasNotes = await page.getByText('foo notes').isVisible();
Expand All @@ -62,7 +82,6 @@ test.describe('Files', () => {
});

test('allows release tags manipulation', async ({ baseUrl, loggedInPage: page }) => {
await page.click(`.leftNav :text('Releases')`);
const alreadyTagged = await page.getByText('some, tags').isVisible();
test.skip(alreadyTagged, 'looks like the release was tagged already');
await page.getByText(/demo-artifact/i).click();
Expand All @@ -87,7 +106,6 @@ test.describe('Files', () => {
});

test('allows release tags reset', async ({ loggedInPage: page }) => {
await page.click(`.leftNav :text('Releases')`);
await page.getByText(/demo-artifact/i).click();
const theDiv = await page
.locator('div')
Expand Down Expand Up @@ -120,7 +138,6 @@ test.describe('Files', () => {
});

test('allows release tags filtering', async ({ loggedInPage: page }) => {
await page.click(`.leftNav :text('Releases')`);
expect(await page.getByText(releaseTag.toLowerCase()).isVisible()).toBeTruthy();
await page.getByPlaceholder(/select tags/i).fill('foo,');
const releasesNote = await page.getByText(/There are no Releases*/i);
Expand Down Expand Up @@ -149,7 +166,6 @@ test.describe('Files', () => {
// })

test('allows artifact downloads', async ({ loggedInPage: page }) => {
await page.click(`.leftNav :text('Releases')`);
await page.click(`text=/mender-demo-artifact/i`);
await page.click('.expandButton');
const downloadButton = await page.getByText(/download artifact/i);
Expand Down

0 comments on commit ac882ea

Please sign in to comment.