From 73ada866421299f8949a494e741b0f75660c6e7c Mon Sep 17 00:00:00 2001 From: Julie Turner Date: Fri, 12 Jan 2024 18:07:31 +0000 Subject: [PATCH] Merge in bcameron1231-v4-Admin --- docs/graph/admin.md | 312 +++++++++++++++++++ docs/graph/analytics.md | 2 +- packages/graph/admin/index.ts | 42 +++ packages/graph/admin/people.ts | 49 +++ packages/graph/admin/serviceAnnouncements.ts | 179 +++++++++++ packages/graph/admin/sharepoint.ts | 24 ++ packages/graph/decorators.ts | 23 ++ packages/queryable/queryable.ts | 1 + test/graph/admin.ts | 181 +++++++++++ test/queryable/invokable.ts | 1 + 10 files changed, 813 insertions(+), 1 deletion(-) create mode 100644 docs/graph/admin.md create mode 100644 packages/graph/admin/index.ts create mode 100644 packages/graph/admin/people.ts create mode 100644 packages/graph/admin/serviceAnnouncements.ts create mode 100644 packages/graph/admin/sharepoint.ts create mode 100644 test/graph/admin.ts diff --git a/docs/graph/admin.md b/docs/graph/admin.md new file mode 100644 index 000000000..ffc6b2fb1 --- /dev/null +++ b/docs/graph/admin.md @@ -0,0 +1,312 @@ +# @pnp/graph/admin + +The ability to work with Microsoft Graph Admin APIs + +## Admin, IAdmin, SharePointSettings, ISharePointSettings, ServiceAnnouncements, IServiceAccouncements, PeopleAdmin, IPeopleAdmin + +[![Invokable Banner](https://img.shields.io/badge/Invokable-informational.svg)](../concepts/invokable.md) [![Selective Imports Banner](https://img.shields.io/badge/Selective%20Imports-informational.svg)](../concepts/selective-imports.md) + + +## SharePoint Settings +### Get SharePoint Tenant Settings + +Using sharePointSettings() you can retrieve the SharePoint Tenant Settings + +```TypeScript +import { graphfi } from "@pnp/graph"; +import "@pnp/graph/admin"; + +const graph = graphfi(...); + +const settings = await graph.admin.sharepoint.settings(); + +``` +### Update SharePoint Tenant Settings + +Update SharePoint Tenant Settings + +```TypeScript +import { graphfi } from "@pnp/graph"; +import "@pnp/graph/admin"; + +const graph = graphfi(...); + +const settings = await graph.admin.sharepoint.settings.update({deletedUserPersonalSiteRetentionPeriodInDays: 5, isCommentingOnSitePagesEnabled: true}); + +``` + +## People + +### Get People Settings + +Represents a setting to control people-related admin settings in the tenant. + +```TypeScript +import { graphfi } from "@pnp/graph"; +import "@pnp/graph/admin"; + +const graph = graphfi(...); + +const peopleSettings = await graph.admin.people(); + +``` +### Get People Pronoun Settings + +Represents the settings that manage the support of pronouns in an organization. + +```TypeScript +import { graphfi } from "@pnp/graph"; +import "@pnp/graph/admin"; + +const graph = graphfi(...); + +const pronounSettings = await graph.admin.people.pronounSettings(); + +``` +### Update People Pronoun Settings + +Update Pronoun Settings in an organization + +```TypeScript +import { graphfi } from "@pnp/graph"; +import "@pnp/graph/admin"; + +const graph = graphfi(...); + +const pronounSettings = await graph.admin.people.pronounSettings.update({ + isEnabledInOrganization:true +}); + +``` +### Profile Card Properties + +Gets a collection profile card properties for an organization + +```TypeScript +import { graphfi } from "@pnp/graph"; +import "@pnp/graph/admin"; + +const graph = graphfi(...); + +const profileCardProperties = await graph.admin.people.profileCardProperties(); + +``` +### Add Profile Card Property + +Add a profile card property. + +```TypeScript +import { graphfi } from "@pnp/graph"; +import "@pnp/graph/admin"; + +const graph = graphfi(...); + +const profileCardProperty = await graph.admin.people.profileCardProperties.add({ + directoryPropertyName: "CustomAttribute1", + annotations: [{ + displayName: "Cost Center", + localizations: [ + { + languageTag: "ru-RU", + displayName: "центр затрат" + } + ] + }] +}); + +``` +### Get Profile Card Property + +Retrieve the properties of a profile card property. + +```TypeScript +import { graphfi } from "@pnp/graph"; +import "@pnp/graph/admin"; + +const graph = graphfi(...); + +const profileCardProperty = await graph.admin.people.profileCardProperties.getById("CustomAttribute1")(); + +``` +### Update Profile Card Property + +Updates the properties of a profile card property. + +```TypeScript +import { graphfi } from "@pnp/graph"; +import "@pnp/graph/admin"; + +const graph = graphfi(...); + +const profileCardProperty = await graph.admin.people.profileCardProperties.getById("CustomAttribute1").update({ + directoryPropertyName: "CustomAttribute1", + annotations: [{ + displayName: "Cost Center 2", + localizations: [ + { + languageTag: "ru-RU", + displayName: "центр затрат" + } + ] + }] +}); + +``` +### Delete Profile Card Property + +Delete a property of a profile card + +```TypeScript +import { graphfi } from "@pnp/graph"; +import "@pnp/graph/admin"; + +const graph = graphfi(...); + +await graph.admin.people.profileCardProperties.getById("CustomAttribute1").delete(); + +``` +## Service Announcements + +### Get Health overviews + +Retrieves the service health report for a tenant + +```TypeScript +import { graphfi } from "@pnp/graph"; +import "@pnp/graph/admin"; + +const graph = graphfi(...); + +const healthOverviews = await graph.admin.serviceAnnouncements.healthOverviews(); + +``` +### Get Service Health By Name + +Retrieves the service health report for a tenant + +```TypeScript +import { graphfi } from "@pnp/graph"; +import "@pnp/graph/admin"; + +const graph = graphfi(...); + +const serviceHealth = await graph.admin.serviceAnnouncements.healthOverviews.getByName("Microsoft 365 suite")(); + +``` +### Get Health Issues + +Retrieves the service health issues for a tenant + +```TypeScript +import { graphfi } from "@pnp/graph"; +import "@pnp/graph/admin"; + +const graph = graphfi(...); + +const issues = await graph.admin.serviceAnnouncements.issues(); + +``` +### Get Health Messages + +Retrieves the service health messages for a tenant + +```TypeScript +import { graphfi } from "@pnp/graph"; +import "@pnp/graph/admin"; + +const graph = graphfi(...); + +const messages = await graph.admin.serviceAnnouncements.messages(); + +``` +### Get Specific Service Health Message + +Retrieves a specific service health message + +```TypeScript +import { graphfi } from "@pnp/graph"; +import "@pnp/graph/admin"; + +const graph = graphfi(...); + +const message = await graph.admin.serviceAnnouncements.messages.getById("MC172851"); + +``` + +### Archive/unarchive Service Health Messages + +Archive the specified service health messages + +```TypeScript +import { graphfi } from "@pnp/graph"; +import "@pnp/graph/admin"; + +const graph = graphfi(...); + +//archive +await graph.admin.serviceAnnouncements.messages.archive(["MC172851","MC172333"]); + +//unarchive +await graph.admin.serviceAnnouncements.messages.unarchive(["MC172851","MC172333"]); + +``` +### Favorite/unfavorite Service Health Messages + +Favorites the specified service health messages + +```TypeScript +import { graphfi } from "@pnp/graph"; +import "@pnp/graph/admin"; + +const graph = graphfi(...); + +//favorite +await graph.admin.serviceAnnouncements.messages.favorite(["MC172851","MC172333"]); + +//unfavorite +await graph.admin.serviceAnnouncements.messages.unfavorite(["MC172851","MC172333"]); + +``` +### Mark as read / Mark unread Service Health Messages + +Marks the specified service health messages as read or unread + +```TypeScript +import { graphfi } from "@pnp/graph"; +import "@pnp/graph/admin"; + +const graph = graphfi(...); + +//mark as read +await graph.admin.serviceAnnouncements.messages.markRead(["MC172851","MC172333"]); + +//mark as unread +await graph.admin.serviceAnnouncements.messages.markUnread(["MC172851","MC172333"]); + +``` +### Get Attachments of Service Health Message + +Get attachments of Service Health Message + +```TypeScript +import { graphfi } from "@pnp/graph"; +import "@pnp/graph/admin"; + +const graph = graphfi(...); + +const attachments = await graph.admin.serviceAnnouncements.messages.getById("MC172851").attachments(); + +``` +### Get Attachment of Service Health Message by id + +Get the specified attachment by id + +```TypeScript +import { graphfi } from "@pnp/graph"; +import "@pnp/graph/admin"; + +const graph = graphfi(...); + +const attachment = await graph.admin.serviceAnnouncements.messages.getById("MC172851").attachments.getById("30356a46-ffad-47e1-acf6-40a99b1538c1") + +``` \ No newline at end of file diff --git a/docs/graph/analytics.md b/docs/graph/analytics.md index d3dc3dd96..21f409591 100644 --- a/docs/graph/analytics.md +++ b/docs/graph/analytics.md @@ -17,7 +17,7 @@ Using analytics() you get the Item Analytics for a Drive Item ```TypeScript import { graphfi } from "@pnp/graph"; import "@pnp/graph/users"; -import "@pnp/graph/drive"; +import "@pnp/graph/files"; import "@pnp/graph/analytics"; import { IAnalyticsOptions } from "@pnp/graph/analytics"; diff --git a/packages/graph/admin/index.ts b/packages/graph/admin/index.ts new file mode 100644 index 000000000..198d1ae6d --- /dev/null +++ b/packages/graph/admin/index.ts @@ -0,0 +1,42 @@ +import { defaultPath } from "../decorators.js"; +import { GraphFI } from "../fi.js"; +import { _GraphQueryable, graphInvokableFactory } from "../graphqueryable.js"; +import { IPeopleAdmin, PeopleAdmin } from "./people.js"; +import { IServiceAccouncements, ServiceAnnouncements} from "./serviceAnnouncements.js"; +import { SharePointAdmin, ISharePointAdmin } from "./sharepoint.js"; + +declare module "../fi" { + interface GraphFI { + readonly admin: IAdmin; + } +} + +defaultPath("admin"); +class _Admin extends _GraphQueryable { + public get people(){ + return PeopleAdmin(this); + } + public get sharepoint() { + return SharePointAdmin(this); + } + public get serviceAnnouncements() { + return ServiceAnnouncements(this); + } +} + +export interface IAdmin { + readonly people: IPeopleAdmin; + readonly sharepoint: ISharePointAdmin; + readonly serviceAnnouncements: IServiceAccouncements; +} + +export const Admin: IAdmin = graphInvokableFactory(_Admin); + + +Reflect.defineProperty(GraphFI.prototype, "admin", { + configurable: true, + enumerable: true, + get: function (this: GraphFI) { + return this.create(Admin, "admin"); + }, +}); diff --git a/packages/graph/admin/people.ts b/packages/graph/admin/people.ts new file mode 100644 index 000000000..b8151c512 --- /dev/null +++ b/packages/graph/admin/people.ts @@ -0,0 +1,49 @@ +import { graphInvokableFactory, _GraphInstance, _GraphCollection } from "../graphqueryable.js"; +import { defaultPath, updateable, IUpdateable, addable, getById, IAddable, deleteable, IDeleteable, IGetById } from "../decorators.js"; +import { ProfileCardProperty as IProfileCardPropertyType, PeopleAdminSettings as IPeopleAdminSettingsType } from "@microsoft/microsoft-graph-types"; + +@defaultPath("people") +export class _PeopleAdmin extends _GraphInstance { + public get profileCardProperties(): IProfileCardProperties { + return ProfileCardProperties(this); + } + public get pronounSettings(): IPronounSettings { + return PronounSettings(this); + } +} + +export interface IPeopleAdmin extends _PeopleAdmin { } +export const PeopleAdmin = graphInvokableFactory(_PeopleAdmin); + +/** +* People Pronoun Settings +*/ +@defaultPath("pronouns") +@updateable() +export class _PronounSettings extends _GraphInstance { } +export interface IPronounSettings extends _PronounSettings, IUpdateable { } +export const PronounSettings = graphInvokableFactory(_PronounSettings); + +/** +* Profilecard Property +*/ +@defaultPath("profileCardProperty") +@deleteable() +@updateable() +export class _ProfileCardProperty extends _GraphInstance { } +export interface IProfileCardProperty extends _ProfileCardProperty, IDeleteable, IUpdateable { } +export const ProfileCardProperty = graphInvokableFactory(_ProfileCardProperty); + +/** +* Profilecard properties +*/ +@defaultPath("profileCardProperties") +@getById(ProfileCardProperty) +@addable() +export class _ProfileCardProperties extends _GraphCollection { } +export interface IProfileCardProperties extends _ProfileCardProperties, IAddable, IGetById { } +export const ProfileCardProperties = graphInvokableFactory(_ProfileCardProperties); + +export interface IPronounSettingsType{ + isEnabledInOrganization: boolean; +} diff --git a/packages/graph/admin/serviceAnnouncements.ts b/packages/graph/admin/serviceAnnouncements.ts new file mode 100644 index 000000000..1c159ec03 --- /dev/null +++ b/packages/graph/admin/serviceAnnouncements.ts @@ -0,0 +1,179 @@ +import { GraphQueryable, _GraphCollection, _GraphInstance, graphGet, graphInvokableFactory, graphPost } from "../graphqueryable.js"; +import { + ServiceAnnouncement as IServiceAnnouncementType, + ServiceHealth as IServiceHealthType, + ServiceAnnouncementAttachment as IServiceAccountAttachmentType, + ServiceHealthIssue as IServiceHealthIssueType, + ServiceUpdateMessage as IServiceMessageType, +} from "@microsoft/microsoft-graph-types"; +import { IGetById, IGetByName, defaultPath, getById, getByName } from "../decorators.js"; +import { body } from "@pnp/queryable"; + +/** + * Tenant Service Announcements + */ +@defaultPath("serviceAnnouncement") +export class _ServiceAnnouncements extends _GraphInstance { + public get healthOverviews(): IHealthOverviews { + return HealthOverviews(this); + } + public get issues(): IHealthIssues { + return HealthIssues(this); + } + public get messages(): IServiceMessages { + return ServiceMessages(this); + } +} + +export interface IServiceAccouncements extends _ServiceAnnouncements { } +export const ServiceAnnouncements = graphInvokableFactory(_ServiceAnnouncements); + +/** + * Service Health Report + */ +export class _ServiceHealth extends _GraphInstance { } +export interface IServiceHealth extends _ServiceHealth { } +export const ServiceHealth = graphInvokableFactory(_ServiceHealth); + +/** + * Service Health reports + */ +@defaultPath("healthOverviews") +@getByName(ServiceHealth) +export class _HealthOverviews extends _GraphCollection { } +export interface IHealthOverviews extends _HealthOverviews, IGetByName { } +export const HealthOverviews = graphInvokableFactory(_HealthOverviews); + +/** + * Health Issue + */ +export class _HealthIssue extends _GraphInstance { } +export interface IHealthIssue extends _HealthIssue { } +export const HealthIssue = graphInvokableFactory(_HealthIssue); + +/** + * Health issues + */ +@defaultPath("issues") +@getById(HealthIssue) +export class _HealthIssues extends _GraphCollection { + /** + * Get incident report. The operation returns an error if the specified issue doesn't exist for the tenant or if PIR document does not exist for the issue. + */ + public get incidentReport(): any { + return graphGet(GraphQueryable(this, "issueReport")); + } +} +export interface IHealthIssues extends _HealthIssues { } +export const HealthIssues = graphInvokableFactory(_HealthIssues); + + +/** + * Service Announcements Messages + */ +export class _ServiceMessage extends _GraphInstance { + /** + * Get message attachment + */ + public get attachments(): any { + return ServiceMessageAttachments(this); + } +} +export interface IServiceMessage extends _ServiceMessage { } +export const ServiceMessage = graphInvokableFactory(_ServiceMessage); + +/** + * Service Announcements Messages + */ +@defaultPath("messages") +@getById(ServiceMessage) +export class _ServiceMessages extends _GraphCollection { + /** + * Archive a list of service messages as read for signed-in user + * + * @param messageIds List of message IDs to mark as read. + */ + public archive(messageIds: string[]): Promise { + return graphPost(ServiceMessages(this, "archive"), body({ + messageIds: messageIds, + })); + } + + /** + * Unarchive a list of service messages as read for signed-in user + * + * @param messageIds List of message IDs to mark as read. + */ + public unarchive(messageIds: string[]): Promise { + return graphPost(ServiceMessages(this, "unarchive"), body({ + messageIds: messageIds, + })); + } + + /** + * Favorite a list of service messages as read for signed-in user + * + * @param messageIds List of message IDs to mark as read. + */ + public favorite(messageIds: string[]): Promise { + return graphPost(ServiceMessages(this, "favorite"), body({ + messageIds: messageIds, + })); + } + + /** + * Unfavorite a list of service messages as read for signed-in user + * + * @param messageIds List of message IDs to mark as read. + */ + public unfavorite(messageIds: string[]): Promise { + return graphPost(ServiceMessages(this, "unfavorite"), body({ + messageIds: messageIds, + })); + } + + /** + * Mark a list of service messages as read for signed-in user + * + * @param messageIds List of message IDs to mark as read. + */ + public markRead(messageIds: string[]): Promise { + return graphPost(ServiceMessages(this, "markRead"), body({ + messageIds: messageIds, + })); + } + + /** + * Mark a list of service messages as unread for signed-in user + * + * @param messageIds List of message IDs to mark as read. + */ + public markUnread(messageIds: string[]): Promise { + return graphPost(ServiceMessages(this, "markUnread"), body({ + messageIds: messageIds, + })); + } +} +export interface IServiceMessages extends _ServiceMessages, IGetById { } +export const ServiceMessages = graphInvokableFactory(_ServiceMessages); + +/** + * Service Announcements Message + */ +export class _ServiceMessageAttachment extends _GraphInstance { } +export interface IServiceMessageAttachment extends _ServiceMessageAttachment { } +export const ServiceMessageAttachment = graphInvokableFactory(_ServiceMessageAttachment); + +/** + * Service Announcements Message + */ +@defaultPath("attachments") +@getById(ServiceMessageAttachment) +export class _ServiceMessageAttachments extends _GraphCollection { } +export interface IServiceMessageAttachments extends _ServiceMessageAttachments { } +export const ServiceMessageAttachments = graphInvokableFactory(_ServiceMessageAttachments); + + +export interface IServiceMessageUpdate { + value: boolean; +} diff --git a/packages/graph/admin/sharepoint.ts b/packages/graph/admin/sharepoint.ts new file mode 100644 index 000000000..bcd1a8216 --- /dev/null +++ b/packages/graph/admin/sharepoint.ts @@ -0,0 +1,24 @@ +import { graphInvokableFactory, _GraphInstance } from "../graphqueryable.js"; +import { defaultPath, updateable, IUpdateable } from "../decorators.js"; +import { SharepointSettings as ISharePointSettingsType } from "@microsoft/microsoft-graph-types"; + +@defaultPath("sharepoint") +export class _SharePointAdmin extends _GraphInstance { + public get settings(): ISharePointSettings { + return SharePointSettings(this); + } +} + +export interface ISharePointAdmin extends _SharePointAdmin { + readonly settings: ISharePointSettings; +} +export const SharePointAdmin = graphInvokableFactory(_SharePointAdmin); + +/** + * SharePoint Tenant Settings + */ +@defaultPath("settings") +@updateable() +export class _SharePointSettings extends _GraphInstance { } +export interface ISharePointSettings extends _SharePointSettings, IUpdateable { } +export const SharePointSettings = graphInvokableFactory(_SharePointSettings); diff --git a/packages/graph/decorators.ts b/packages/graph/decorators.ts index f1b42a861..e83f9de78 100644 --- a/packages/graph/decorators.ts +++ b/packages/graph/decorators.ts @@ -161,3 +161,26 @@ export interface IGetById { */ getById(id: T): R; } + +/** + * Adds the getByName method to a collection + */ +export function getByName(factory: (...args: any[]) => R) { + // eslint-disable-next-line @typescript-eslint/ban-types + return function (target: T) { + + return class extends target { + public getByName(this: IGraphQueryable, name: string): R { + return factory(this, name); + } + }; + }; +} +export interface IGetByName { + /** + * Adds a new item to this collection + * + * @param props properties used to create the new thread + */ + getByName(name: T): R; +} diff --git a/packages/queryable/queryable.ts b/packages/queryable/queryable.ts index 20a6028a2..0a372afb7 100644 --- a/packages/queryable/queryable.ts +++ b/packages/queryable/queryable.ts @@ -1,3 +1,4 @@ +/* eslint-disable @typescript-eslint/no-unsafe-declaration-merging */ import { combine, getGUID, Timeline, asyncReduce, reduce, broadcast, request, isArray, TimelinePipe, lifecycle, stringIsNullOrEmpty } from "@pnp/core"; import { IInvokable, invokable } from "./invokable.js"; diff --git a/test/graph/admin.ts b/test/graph/admin.ts new file mode 100644 index 000000000..6dd5bc495 --- /dev/null +++ b/test/graph/admin.ts @@ -0,0 +1,181 @@ +import { expect } from "chai"; +import { getRandomString, stringIsNullOrEmpty } from "@pnp/core"; +import { pnpTest } from "../pnp-test.js"; +import "@pnp/graph/admin"; + +describe("Admin", function () { + const customUserProperty = "CustomAttribute1"; + let propertyId = ""; + + // Ensure we have the data to test against + before(async function () { + + if (!this.pnp.settings.enableWebTests || stringIsNullOrEmpty(this.pnp.settings.testUser)) { + this.skip(); + } + + // Get a sample property + try { + const property = await this.pnp.graph.admin.people.profileCardProperties.add({ + directoryPropertyName: customUserProperty, + annotations: [{ + displayName: "Cost Center", + localizations: [ + { + languageTag: "ru-RU", + displayName: "центр затрат", + }, + ], + }], + }); + propertyId = property.id; + } catch (err) { + console.log("Could not set test values for Admin"); + } + }); + + describe("SharePoint", function () { + it("Get SharePoint Settings", pnpTest("923c1bd6-8621-41d2-9ea9-004a4a735c9f", async function () { + const sharePointSettings = await this.pnp.graph.admin.sharepoint.settings(); + return expect(sharePointSettings.availableManagedPathsForSiteCreation.length > 0).is.true; + })); + + it("Update SharePoint Settings", pnpTest("bbf52535-3a7e-452b-b0eb-9940832163aa", async function () { + const sharePointSettings = await this.pnp.graph.admin.sharepoint.settings.update({ deletedUserPersonalSiteRetentionPeriodInDays: 30 }); + return expect(sharePointSettings.deletedUserPersonalSiteRetentionPeriodInDays === 30).is.true; + })); + }); + + describe("People", function () { + it("Get People Settings", pnpTest("9bd5a022-65d3-4a34-b8c4-c74381b98551", async function () { + const settings = await this.pnp.graph.admin.people(); + return expect(settings.profileCardProperties).is.not.null; + })); + + it("Get Pronoun Settings", pnpTest("bbc0e5af-3620-4164-9120-556ac534db39", async function () { + const settings = await this.pnp.graph.admin.people.pronounSettings(); + return expect(settings.isEnabledInOrganization).to.be.an("boolean"); + })); + + it.skip("Update Pronoun Settings", pnpTest("830c2b41-5642-40d6-8585-3e26207e3f13", async function () { + const settings = await this.pnp.graph.admin.people.pronounSettings.update({ + isEnabledInOrganization: true, + }); + return expect(settings.isEnabledInOrganization).is.true; + })); + + it.skip("Add Profile Card Property", pnpTest("49b98899-0af3-4b8b-8f66-3748410420b7", async function () { + const property = await this.pnp.graph.admin.people.profileCardProperties.add({ + directoryPropertyName: "CustomAttribute2", + annotations: [{ + displayName: "Cost Center", + localizations: [ + { + languageTag: "ru-RU", + displayName: "центр затрат", + }, + ], + }], + }); + return expect(property.id).is.not.null; + })); + + it.skip("Get Profile Card Property", pnpTest("05d8f50a-1b47-4631-9576-2aa3c5efcf75", async function () { + const property = await this.pnp.graph.admin.people.profileCardProperties.getById(customUserProperty)(); + return expect(property.id).is.not.null; + })); + + it.skip("Update Profile Card Property", pnpTest("04fb914e-41c6-4b8e-a326-63c41e6672a4", async function () { + const displayName = getRandomString(5) + "Cost Center"; + const property = await this.pnp.graph.admin.people.profileCardProperties.getById(customUserProperty).update({ + directoryPropertyName: this.customUserProperty, + annotations: [{ + displayName: getRandomString(5) + "Cost Center", + localizations: [ + { + languageTag: "ru-RU", + displayName: "центр затрат", + }, + ], + }], + }); + return expect(property.annotations[0]?.displayName).equals(displayName); + })); + + it.skip("Delete Profile Card Property", pnpTest("fbfae956-d776-4bd7-8ad2-3db384ec02c3", async function () { + const property = await this.pnp.graph.admin.people.profileCardProperties.add({ + directoryPropertyName: getRandomString(5) + "CustomAttribute2", + annotations: [{ + displayName: "Cost Center", + localizations: [ + { + languageTag: "ru-RU", + displayName: "центр затрат", + }, + ], + }], + }); + const response = await this.pnp.graph.admin.people.profileCardProperties.getById(property.id).delete(); + return expect(response).is.ok; + })); + }); + + describe("Service Health", function () { + it("Get Health Overviews", pnpTest("79f7392b-053d-44a0-87f6-a1c2332d6841", async function () { + const healthOverviews = await this.pnp.graph.admin.serviceAnnouncements.healthOverviews(); + return expect(healthOverviews).to.be.an("array"); + })); + + it("Get Health By Service Name", pnpTest("f06cd76b-3a61-4728-ba5e-f97bb6e718a8", async function () { + const serviceHealth = await this.pnp.graph.admin.serviceAnnouncements.healthOverviews.getByName("Microsoft 365 suite")(); + return expect(serviceHealth).has.property("id"); + })); + + it("Get Health Issues", pnpTest("6b04e99e-dcbb-48ee-87c2-4d17b1fad12d", async function () { + const issues = await this.pnp.graph.admin.serviceAnnouncements.issues(); + return expect(issues).to.be.an("array"); + })); + + it("Get Health Messages", pnpTest("d06cd76b-3a61-4728-ba5e-f97bb6e718a8", async function () { + const messages = await this.pnp.graph.admin.serviceAnnouncements.messages(); + return expect(messages).to.be.an("array"); + })); + + it("Get Health Message by ID", pnpTest("2cc3edd5-b7af-4967-b8b4-840d161f1b61", async function () { + const messages = await this.pnp.graph.admin.serviceAnnouncements.messages(); + + const messageById = await this.pnp.graph.admin.serviceAnnouncements.messages.getById(messages[0]?.id)(); + return expect(messageById).is.not.null; + })); + + it("Get Health Message Attachments", pnpTest("2e26b2a1-5ce8-4cf9-a0dc-4decddba5641", async function () { + const messages = await this.pnp.graph.admin.serviceAnnouncements.messages(); + + const attachments = await this.pnp.graph.admin.serviceAnnouncements.messages.getById(messages[0]?.id).attachments(); + return expect(attachments).to.be.an("array"); + })); + + it("Get Health Message Attachments by Id", pnpTest("2cef2a70-31c9-4180-91bf-f0bab86e3501", async function () { + const messages = await this.pnp.graph.admin.serviceAnnouncements.messages(); + const attachments = await this.pnp.graph.admin.serviceAnnouncements.messages.getById(messages[0]?.id).attachments(); + const attachmentById = await this.pnp.graph.admin.serviceAnnouncements.messages.getById(attachments[0]?.id)(); + + return expect(attachmentById).is.ok; + })); + }); + + + after(async function () { + + if (!stringIsNullOrEmpty(propertyId)) { + try { + + await this.pnp.graph.admin.people.profileCardProperties.getById(propertyId).delete(); + + } catch (err) { + console.error(`Cannot clean up test property: ${propertyId}`); + } + } + return; + }); +}); diff --git a/test/queryable/invokable.ts b/test/queryable/invokable.ts index 22b801982..92c1a34f7 100644 --- a/test/queryable/invokable.ts +++ b/test/queryable/invokable.ts @@ -1,3 +1,4 @@ +/* eslint-disable @typescript-eslint/no-unsafe-declaration-merging */ import { expect } from "chai"; import { invokable,