Selenium MVP is a PowerShell module that uses PowerShell Selenium combined with a Domain Specific Language (DSL) to automate MVP Submissions. This module targets first time MVP nominees who don't have access to the API. Update: The MVP API has been deprecated, existing MVPs can leverage the module as well.
- Automates MVP Submissions using the Portal.
- Required for existing and nominees since the API has been deprecated.
- Written in a custom DSL (Domain Specific Language)
- PowerShell Selenium
- Windows PowerShell 5.1 (Minimum)
Please note that this Module is not supported on PowerShell Core.
Install-Module SelMVP
Install-Module Selenium
For the best experience, Mozilla Firefox is recommended.
As newer browsers are released, older versions of the WebDrivers need to be updated. Currently, there is no method for correcting these automatically. When updating, download the same version that your browser is. To check your version, you can:
To update the Web Driver, head over to the following links:
Note: Please download the x64 bit build of the driver. The x86 version will not work.
Once downloaded, unblock and extract the driver to the 'Assemblies' sub-directory within the Selenium PowerShell directory.
To determine the location of the Module, you can run the following PowerShell:
Import-Module Selenium ; Get-Module Selenium | Select-Object Path
# Connect to Portal
ConnectTo-MVPPortal -URLPath "https://Your-URL-Path-Goes-Here.com"
OR if you want to specify the DriverType explicitly:
# Connect to Portal
ConnectTo-MVPPortal -URLPath "https://Your-URL-Path-Goes-Here.com" -DriverType ('Firefox','Chrome' or 'Edge')
# Import the CSV File and Parse it. Note that the headers for the Activity Need to be Present:
MVPActivity -CSVPath 'Path to CSV File'
Example CSV File:
Date,Title,URL,Description,Number of Articles,Number of Views,Area,ContributionArea,SecondContributionArea,ThirdContributionArea,Visibility
28/11/2020,TEST,https://www.google.com,TEST,1,1,Article,PowerShell,Networking,Storage,Microsoft
28/11/2020,TEST,https://www.google.com,TEST,1,1,Article,PowerShell,Networking,Storage,Everyone
# Define Activity
MVPActivity [String]"Name of Activity" [-ArgumentList [Hashtable[]]$params] [-CSVPath [String]'CSVPath'] {
param()
*[Optional]* Visibility [String]"Microsoft"
Area [String]"Area"
ContributionArea [String[]]"ContributionArea"
Value [String]"TextName" [String]"TextValue"
}
# Name your activity
MVPActivity "Article Contributions" {
Area 'Article'
# ContributionArea can accept an Array
Visibility 'Microsoft'
ContributionArea 'PowerShell','Yammer','Word'
Value 'Date' '08/05/2021'
Value 'Title' 'TEST'
Value 'URL' 'https:\\test.com'
Value 'Description' 'THIS IS A TEST'
Value 'Number of Articles' '1'
# Or you can use the HTML DivId
Value 'Number of Views' 1
}
OR
# Name your activity
MVPActivity "Reddit Contribution" {
Area 'Forum Participation (3rd Party forums)'
Visibility 'Everyone'
# ContributionArea can be individually
ContributionArea 'PowerShell'
ContributionArea 'Yammer'
ContributionArea 'Word'
Value -Name 'Date' -Value '08/05/2021'
Value 'Title' 'TEST'
Value 'URL' 'https:\\test.com'
Value 'Description' 'THIS IS A TEST'
Value 'Number of Articles' '1'
# Or you can use the HTML DivId
Value 'Number of Views' 1
}
#
# Parameters can be parsed into the Fixture as a HashTable
#
$params = @{
Area = "Blog/Website Post"
ContributionArea = "PowerShell","Yammer","Word"
date = '26/10/2020'
Visibility = 'Everyone'
}
# Define Activity
MVPActivity "Name of Activity" -ArgumentList $params {
# If the Parameters -Area or -ContributionArea are defined
# in the param block, the cmdlet is not required (Area or ContributionArea).
param($Area, $ContributionArea, $Visibility, $date)
# You can use the String Name
Value 'Date' $date
Value 'Title' 'TEST'
Value 'URL' 'https:\\test.com'
Value 'Description' 'THIS IS A TEST'
Value 'Number of Posts' '1'
# Or you can use the HTML Div Id
Value 'Number of Subscribers' '1'
Value 'Annual Unique Visitors' '1'
# Still can execute PowerShell within the script block
Start-Sleep -Seconds 3
}
OR
#
# For those who love complexity, the Fixture supports an array of HashTables to be parsed
# into the Fixture.
#
$params = @(
@{
Area = "Blog/Website Post"
ContributionArea = "PowerShell","Yammer","Word"
Visibility = "Microsoft"
date = '26/10/2020'
}
@{
Area = "Blog/Website Post"
ContributionArea = "PowerShell","Yammer","Word"
Visibility = "Everyone"
date = '15/10/2020'
}
)
# Define Activity
MVPActivity "Name of Activity" -ArgumentList $params {
# If the Parameters -Area or -ContributionArea are defined in the param block,
# the cmdlet is not required (Area or ContributionArea).
param($Area, $ContributionArea, $Visibility, $date)
# You can use the String Name
Value 'Date' $date
Value 'Title' 'TEST'
Value 'URL' 'https:\\test.com'
Value 'Description' 'THIS IS A TEST'
Value 'Number of Posts' '1'
# Or you can use the HTML Div Id
Value 'Number of Subscribers' '1'
Value 'Annual Unique Visitors' '1'
# Still can execute PowerShell within the script block
Start-Sleep -Seconds 3
}
MVPActivity
is the top-level definition command, which groups the MVP contribution types into their respective areas.
For Example: In the example below, I have a personal blog which I would like to group all my content:
MVPActivity "Personal Blogs" {
Area 'Article'
}
This grouping is not specific to the Activity to have multiple MVPActivities
with the same Area.
For Example:
MVPActivity "Personal Blogs" {
Area 'Blog/Website Post'
Visibility 'Everyone'
ContributionArea 'PowerShell'
Value 'Date' '19/11/2020'
Value 'Title' 'TEST'
Value 'URL' 'https:\\test.com'
Value 'Description' 'THIS IS A TEST'
Value 'Number of Posts' '1'
# Or you can use the HTML Div Id
Value 'Number of Subscribers' '1'
Value 'Annual Unique Visitors' '1'
}
MVPActivity "Another Random Blog" {
Area 'Blog/Website Post'
ContributionArea 'PowerShell'
Value 'Date' '19/11/2020'
Value 'Title' 'TEST2'
Value 'URL' 'https:\\test.com'
Value 'Description' 'THIS IS A TEST2'
Value 'Number of Posts' '1'
# Or you can use the HTML Div Id
Value 'Number of Subscribers' '1'
Value 'Annual Unique Visitors' '1'
}
MVPActivity
supports arguments being parsed into it using the -ArgumentList
parameter, similarly to the -TestCases parameter within Pester. Input is defined as a [HashTable]
or a [HashTable[]]
.
Now we can refactor this logic to take advantage of the -ArgumentList
parameter:
$arguments = @(
@{
Area = 'Blog/Website Post'
ContributionArea = 'PowerShell'
Visibility = 'Everyone'
Date = '19/11/2020'
Title = 'TEST'
Url = 'https:\\test.com'
Description = 'THIS IS A TEST'
NumberOfPosts = 1
NumberOfSubscribers = 1
NumberOfVisitors = 1
},
@{
Area = 'Blog/Website Post'
ContributionArea = 'PowerShell'
Visibility = 'Microsoft'
Date = '19/11/2020'
Title = 'TEST2'
Url = 'https:\\test.com'
Description = 'THIS IS A TEST2'
NumberOfPosts = 1
NumberOfSubscribers = 1
NumberOfVisitors = 1
}
)
MVPActivity "Another Random Blog" -ArgumentList $arguments {
param($Area, $ContributionArea, $Visibility, $Date, $Title, $Url, $Description, $NumberOfPosts, $NumberOfSubscribers, $NumberOfVisitors)
Area $Area
ContributionArea $ContributionArea
Visibility $Visibility
Value 'Date' $Date
Value 'Title' $Title
Value 'URL' $Url
Value 'Description' $Description
Value 'Number of Posts' $NumberOfPosts
Value 'Number of Subscribers' $NumberOfSubscribers
Value 'Annual Unique Visitors' $NumberOfVisitors
}
The code block can be refactored further. The DSL enables automatic Area and ContributionArea execution within the Fixture only by including $Area
or $ContributionArea
within the parameter:
$arguments = @(
@{
Area = 'Blog/Website Post'
ContributionArea = 'PowerShell'
Visibility = 'Microsoft'
Date = '19/11/2020'
Title = 'TEST'
Url = 'https:\\test.com'
Description = 'THIS IS A TEST'
NumberOfPosts = 1
NumberOfSubscribers = 1
NumberOfVisitors = 1
},
@{
Area = 'Blog/Website Post'
ContributionArea = 'PowerShell'
Visibility = 'Microsoft'
Date = '19/11/2020'
Title = 'TEST2'
Url = 'https:\\test.com'
Description = 'THIS IS A TEST2'
NumberOfPosts = 1
NumberOfSubscribers = 1
NumberOfVisitors = 1
}
)
MVPActivity "Another Random Blog" -ArgumentList $arguments {
param($Area, $ContributionArea, $Visibility, $Date, $Title, $Url, $Description, $NumberOfPosts, $NumberOfSubscribers, $NumberOfVisitors)
# Removed $Area and $ContributionArea, since they are included in the Fixture's param block.
Value 'Date' $Date
Value 'Title' $Title
Value 'URL' $Url
Value 'Description' $Description
Value 'Number of Posts' $NumberOfPosts
Value 'Number of Subscribers' $NumberOfSubscribers
Value 'Annual Unique Visitors' $NumberOfVisitors
}
Area
is a command that defines the MVP Contribution Area in the Portal. Area
can only be used within MVPActivity.
Usage:
MVPActivity "Test" {
# Specify the Area. In this instance we are specifying the article.
Area 'Article'
}
Area
is not required to be included when $Area
is added to the param()
within the Fixture. For Example:
MVPActivity "Test" -ArgumentList $params {
param($Area)
}
The Current List of Areas are:
- Article
- Blog/WebSite Post
- Book (Author)
- Book (Co-Author)
- Conference (Staffing)
- Docs.Microsoft.com Contribution
- Forum Moderator
- Forum Participation (3rd Party forums)
- Forum Participation (Microsoft Forums)
- Mentorship
- Microsoft Open Source Projects
- Non-Microsoft Open Source Projects
- Organizer (User Group/Meetup/Local Events)
- Organizer of Conference
- Other
- Product Group Feedback
- Sample Code/Projects/Tools
- Site Owner
- Speaking (Conference)
- Speaking (User Group/Meetup/Local events)
- Technical Social Media (Twitter, Facebook, LinkedIn...)
- Translation Review, Feedback and Editing
- Video/Webcast/Podcast
- Workshop/Volunteer/Proctor
The ContributionArea defines the Contribution Areas within a contribution. ContributionArea can be used as a String Array (ContributionArea 'Area1','Area2','Area3'), or by specifying multiple ContributionArea statements.
Similarly to Area, if ContributionArea is included within the Param() block, it's not required to be defined and will be automatically invoked.
The current list of 'Contribution Areas' are:
- Chef/Puppet in Datacenter
- Container Management
- Datacenter Management
- Group Policy
- High Availability
- Hyper-V
- Linux in System Center/Operations Management Suite
- Linux on Hyper-V
- Networking
- PowerShell
- Storage
- Windows Server for Small & Medium Business
- Azure Bot Service
- Azure Cognitive Search
- Azure Cognitive Services
- Azure Machine Learning
- Dynamics 365
- Power Apps
- Power Automate
- Power Pages
- Power Virtual Agents
- Azure Arc Enabled Data Services
- Azure Cosmos DB
- Azure Data Catalog
- Azure Data Explorer
- Azure Data Lake
- Azure Database for MySQL
- Azure Database for PostgreSQL
- Azure Databricks
- Azure HDInsight and Hadoop & Spark on Azure
- Azure Search
- Azure SQL (Database, Pools, Serverless, Hyperscale, Managed Instance, Virtual Machines)
- Azure SQL Edge
- Azure Stream Analytics
- Azure Synapse Analytics
- Big Data Clusters
- Cortana Intelligence Suite
- Data Warehousing (Azure SQL Data Warehouse, Fast Track & APS)
- Information Management (ADF, SSIS, & Data Sync)
- Microsoft Purview
- Power BI
- SQL Server (on Windows, Linux, Containers)
- SQL Server Machine Learning Services (R, Python)
- SQL Server Reporting Services & Analysis Services
- Tools & Connectivity
- .NET
- Accessibility
- ASP.NET/IIS
- C++
- Developer Security
- Front End Web Dev
- Github & Azure DevOps
- Java
- Javascript/Typescript
- Node.js
- Python
- Quantum
- Unity
- Visual Studio Code
- Visual Studio Extensibility
- Xamarin
- Information Protection
- Microsoft Intune
- Previous Expertise: Directory Services
- Remote Desktop Services
- Azure Edge Devices
- Azure IoT Services & Development
- Access
- Excel
- Exchange
- Microsoft Stream
- Microsoft Teams
- Microsoft Viva
- Office 365
- OneDrive
- OneNote
- Outlook
- PowerPoint
- Project
- SharePoint
- Skype for Business
- Visio
- Word
- Yammer
- Microsoft Graph
- Microsoft Teams Development
- Outlook Development
- SharePoint Development
- W/X/P Development
- ARM Templates (Infra as Code)
- Azure API Management
- Azure App Service
- Azure Arc Enabled Infrastructure
- Azure Backup & Disaster Recovery
- Azure Blockchain
- Azure Core Compute (VMSS, Confidential Computing, Platform Deployment)
- Azure Cost Management
- Azure Functions
- Azure Hybrid
- Azure Kubernetes, Container Instances, Docker
- Azure Lighthouse
- Azure Logic Apps
- Azure Migrate
- Azure Monitor
- Azure Networking
- Azure Policy & Governance
- Azure SDK (Software Development Kit) and CLIs ( Az CLI, PowerShell, Terraform, Ansible)
- Azure Service Fabric
- Azure Storage
- Distributed App Runtime (Dapr), Open App Model (OAM), Open Service Mesh (OSM)
- Previous Expertise: Microsoft Azure
- Service Bus, Event Hubs, Event Grid, Relay
- D365 Mixed Reality
- MR Design
- MR Development
- Cloud Security
- Identity & Access
- SIEM & XDR
- Surface for IT
- Windows 365
- Windows for IT
- Windows Design
- Windows Development
Single:
MVPActivity "Test" {
ContributionArea 'Area1','Area2','Area3'
}
Multiple:
MVPActivity "Test" {
ContributionArea 'Area1'
ContributionArea 'Area2'
ContributionArea 'Area3'
}
Param Block:
MVPActivity "Test" {
Param($ContributionArea)
# ContributionArea is not required when included in the Param Block.
}
The 'Visibility' Parameter sets the visibility of the Activity. This statement can be included within the fixture or executed within the Param Block, similar to 'Area' and 'Contribution Area'. Multiple statements aren't allowed within the Fixture.
In this example, 'Visibility' is set within the Fixture:
MVPActivity "Test" {
# Let's set the Area and the Contribution Area
Area 'Article'
Visibility 'Microsoft'
# We can set the mandatory parameters
Value "Number of Articles" 1
Value Title "Test Entry"
Value Date "30/11/2020"
}
In this example, 'Visibility' is set within the param block:
MVPActivity "Test" {
param($Visibility)
# Let's set the Area and the Contribution Area
Area 'Article'
# We can set the mandatory parameters
Value "Number of Articles" 1
Value Title "Test Entry"
Value Date "30/11/2020"
}
The Value
command input's the data into the HTML form, using the 'Name' (Being the HTML Div Element ID or Text Name) and 'Value' (Corresponding Value) syntax. Since different Area's have various fields, you can use Get-AreaNamedValues 'AreaName'
to identify the fields.
Value
is mandatory, withinMVPActivity
and won't invoke when specified within theParam()
bock.
In the example below, we will use Get-AreaNamedValues 'Article'
to get the Value
names:
Get-AreaNamedValues Article
Name Mandatory
---- ---------
Number of Articles True
Title True
Date True
Number of Views False
URL False
Description False
Once the list is returned, we can construct the data structure using the output:
MVPActivity "Test" {
# Let's set the Area and the Contribution Area
Area 'Article'
ContributionArea 'PowerShell'
# We can set the mandatory parameters
Value "Number or Articles" 1
Value Title "Test Entry"
Value Date "30/11/2020"
}
Value
supports the auto-formatting of inputted data to meet the requirements of the MVP Portal.
Currently, the following Portal dependencies are auto-formatted:
- Date (Required to be US Date Format) (MM-DD-YYYY)
- URL (Required to meet URL format) (https://site.com)
- Fork and Clone the Repo
git clone "https://github.com/ZanattaMichael/SelMVP.git" dirpath
- Update.
- Load the Module by running:
SelMVP\Build\LocalLoader.ps1
. - Update Changes and Push.
- Raise Pull Request.
- Sit Back and Relax.
- Clone the Repo
git clone "https://github.com/ZanattaMichael/SelMVP.git" dirpath
- Open VSCode
- Run 'Build Module' Task
OR
- Clone the Repo
git clone "https://github.com/ZanattaMichael/SelMVP.git" dirpath
- Run '\Build\BuildModule.ps1'
- You can run the tests locally by running the "Run Pester Tests" VSCode Task.
- If you want to test the Module locally without importing the Module, you can run:
SelMVP\Build\LocalLoader.ps1
. This script will dot-source the functions and dll's needed. - I have created a React Site that emulates the functionality of the Portal. Moving forward, I plan to add integration tests against this Portal.