show serial for fully managed android (#40184)

<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** Resolves #40116

This PR also fixes a weird bug that could cause a crash on host details
page, if hosts.users array was missing

<img width="1350" height="472" alt="image"
src="https://github.com/user-attachments/assets/48aba9a3-6145-4a0c-bab0-c99c3345040a"
/>


# Checklist for submitter

If some of the following don't apply, delete the relevant line.

## Testing

- [x] Added/updated automated tests
- [x] QA'd all new/changed functionality manually
This commit is contained in:
Magnus Jensen
2026-02-20 11:40:31 -05:00
committed by GitHub
parent 2b9cc1f3d0
commit 0130848f6e
3 changed files with 33 additions and 36 deletions
@@ -669,7 +669,7 @@ const HostDetailsPage = ({
useEffect(() => {
setUsersState(() => {
return (
host?.users.filter((user) => {
host?.users?.filter((user) => {
return user.username
.toLowerCase()
.includes(usersSearchString.toLowerCase());
@@ -9,18 +9,19 @@ import { DEFAULT_EMPTY_CELL_VALUE } from "utilities/constants";
import Vitals from "./Vitals";
describe("Vitals Card component", () => {
it("renders only the device Hardware model for Android hosts that were not enrolled in MDM personally", () => {
it("renders the device Hardware model and Serial number for Android hosts that were not enrolled in MDM personally", () => {
const mockHost = createMockHost({
platform: "android",
hardware_model: "Pixel 6",
hardware_serial: "",
hardware_serial: "1234567890",
});
render(<Vitals vitalsData={mockHost} mdm={mockHost.mdm} />);
expect(screen.getByText("Hardware model")).toBeInTheDocument();
expect(screen.getByText("Pixel 6")).toBeInTheDocument();
expect(screen.queryByText("Serial number")).not.toBeInTheDocument();
expect(screen.getByText("Serial number")).toBeInTheDocument();
expect(screen.getByText("1234567890")).toBeInTheDocument();
expect(screen.queryByText("Enrollment ID")).not.toBeInTheDocument();
expect(screen.queryByText("Private IP address")).not.toBeInTheDocument();
expect(screen.queryByText("Public IP address")).not.toBeInTheDocument();
@@ -309,38 +309,34 @@ const Vitals = ({
}
// Device identity
if (!(isAndroidHost && mdm && mdm.enrollment_status !== "On (personal)")) {
if (mdm && isBYODAccountDrivenUserEnrollment(mdm.enrollment_status)) {
// Personal (BYOD) devices do not report their serial numbers, so show the enrollment id instead.
vitals.push({
sortKey: "Enrollment ID",
element: (
<DataSet
key="enrollment-id"
title={
<TooltipWrapper tipContent="Enrollment ID is a unique identifier for personal hosts. Personal (BYOD) devices don't report their serial numbers. The Enrollment ID changes with each enrollment.">
Enrollment ID
</TooltipWrapper>
}
value={<TooltipTruncatedText value={vitalsData.uuid} />}
/>
),
});
} else {
// for all other host types, show the serial number
vitals.push({
sortKey: "Serial number",
element: (
<DataSet
key="serial-number"
title="Serial number"
value={
<TooltipTruncatedText value={vitalsData.hardware_serial} />
}
/>
),
});
}
if (mdm && isBYODAccountDrivenUserEnrollment(mdm.enrollment_status)) {
// Personal (BYOD) devices do not report their serial numbers, so show the enrollment id instead.
vitals.push({
sortKey: "Enrollment ID",
element: (
<DataSet
key="enrollment-id"
title={
<TooltipWrapper tipContent="Enrollment ID is a unique identifier for personal hosts. Personal (BYOD) devices don't report their serial numbers. The Enrollment ID changes with each enrollment.">
Enrollment ID
</TooltipWrapper>
}
value={<TooltipTruncatedText value={vitalsData.uuid} />}
/>
),
});
} else {
// for all other host types, show the serial number
vitals.push({
sortKey: "Serial number",
element: (
<DataSet
key="serial-number"
title="Serial number"
value={<TooltipTruncatedText value={vitalsData.hardware_serial} />}
/>
),
});
}
// Hardware model