Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Merge branch 'qa'

Conflicts:
	src/NuGetGallery/Views/Packages/DisplayPackage.cshtml
  • Loading branch information...
commit b394324938cb69dc368d4972aa87d9c0b1eafeef 2 parents 48c9aee + 2395b16
@anurse anurse authored
Showing with 4,689 additions and 50 deletions.
  1. +148 −0 README.markdown.orig
  2. +19 −0 ops/Modules/NuGetOps/NuGetOps.psm1
  3. +10 −0 ops/Modules/NuGetOps/Private/ParseConfigurationSettings.ps1
  4. +33 −0 ops/Modules/NuGetOps/Public/Get-Configuration.ps1
  5. +25 −0 ops/Modules/NuGetOps/Public/Get-ConfigurationSettings.ps1
  6. +128 −0 src/NuGetGallery.Backend.Cloud/NuGetGallery.Backend.Cloud.ccproj.orig
  7. +284 −0 src/NuGetGallery.Operations/Tasks/HandleQueuedPackageEditsTask.cs.orig
  8. +2 −1  src/NuGetGallery.Operations/Tasks/ReplicatePackageStatisticsTask.cs
  9. +2 −2 src/NuGetGallery/Controllers/ApiController.cs
  10. +80 −0 src/NuGetGallery/ViewModels/ReportAbuseViewModel.cs.orig
  11. +47 −0 src/NuGetGallery/Views/Packages/ContactOwners.cshtml.orig
  12. +4 −4 src/NuGetGallery/Views/Packages/DisplayPackage.cshtml
  13. +101 −0 src/NuGetGallery/Views/Packages/ReportAbuse.cshtml.orig
  14. +58 −0 src/NuGetGallery/Views/Packages/ReportMyPackage.cshtml.orig
  15. +6 −0 tests/.nuget/NuGet.Config
  16. +153 −0 tests/.nuget/NuGet.targets
  17. +31 −0 tests/Local.testsettings
  18. +4 −2 tests/NuGetGallery.Facts/Controllers/ApiControllerFacts.cs
  19. +6 −0 tests/NuGetGallery.FunctionalTests.Fluent/App.config
  20. +128 −0 tests/NuGetGallery.FunctionalTests.Fluent/EditPackageAsPartOfUploadTest.cs
  21. +119 −0 tests/NuGetGallery.FunctionalTests.Fluent/EditPackageTest.cs
  22. +49 −0 tests/NuGetGallery.FunctionalTests.Fluent/ExtensionMethods.cs
  23. +62 −0 tests/NuGetGallery.FunctionalTests.Fluent/LogonTest.cs
  24. +50 −0 tests/NuGetGallery.FunctionalTests.Fluent/MinClientVersionFromUITest.cs
  25. +47 −0 tests/NuGetGallery.FunctionalTests.Fluent/NuGetFluentTest.cs
  26. +104 −0 tests/NuGetGallery.FunctionalTests.Fluent/NuGetGallery.FunctionalTests.Fluent.csproj
  27. +8 −0 tests/NuGetGallery.FunctionalTests.Fluent/Pages.csv
  28. +36 −0 tests/NuGetGallery.FunctionalTests.Fluent/Properties/AssemblyInfo.cs
  29. +56 −0 tests/NuGetGallery.FunctionalTests.Fluent/StatisticsPageTest.cs
  30. +8 −0 tests/NuGetGallery.FunctionalTests.Fluent/packages.config
  31. +1 −1  tests/NuGetGallery.FunctionalTests.Helpers/NuspecHelper.cs
  32. +53 −0 tests/NuGetGallery.FunctionalTests.vsmdi
  33. +64 −29 tests/NuGetGallery.FunctionalTests/Features/CuratedFeedTest.cs
  34. +23 −0 tests/NuGetGallery.FunctionalTests/ODataTests/V2FeedExtendedTest.cs
  35. +4 −4 tests/NuGetGallery.FunctionalTests/WebUITests/AccountManagement/InvalidLogonTest.cs
  36. +1 −1  tests/NuGetGallery.FunctionalTests/WebUITests/AssertAndValidationHelper.cs
  37. +13 −5 tests/NuGetGallery.FunctionalTests/WebUITests/PackageManagement/EditPackageTest.cs
  38. +8 −1 tests/NuGetGallery.FunctionalTests/WebUITests/UploadAndDownload/AggregateStatsAfterDownload.cs
  39. +58 −0 tests/Scripts/AutoDeploy.ps1
  40. +21 −0 tests/Scripts/NuGetGallery.FunctionalTests.msbuild
  41. +2 −0  tests/Scripts/RunEverythingy.cmd
  42. +12 −0 tests/Scripts/RunSpecificTests.cmd
  43. +5 −0 tests/Scripts/RunTests.cmd
  44. +104 −0 tests/Scripts/RunTestsFluent.cmd
  45. +5 −0 tests/Scripts/TestRunSetupScript.cmd
  46. +5 −0 tests/Scripts/TestRunSetupScriptFluent.cmd
  47. +20 −0 tests/Scripts/UpdateConfig.ps1
  48. +2,482 −0 tests/Scripts/fluentresults.txt
View
148 README.markdown.orig
@@ -0,0 +1,148 @@
+[NuGet Gallery](http://nuget.org/) - Where packages are found
+=======================================================================
+This is an implementation of the NuGet Gallery and API. This serves as the back-end and community
+website for the NuGet client. For information about the NuGet clients, visit http://nuget.codeplex.com/
+
+## Build and Run the Gallery in (arbitrary number) easy steps
+
+1. Prerequisites. Install these if you don't already have them:
+ 1. Visual Studio 2012
+ 2. PowerShell 2.0 (comes with Windows 7+)
+ 3. [NuGet](http://docs.nuget.org/docs/start-here/installing-nuget)
+ 4. [Windows Azure SDK v2.2](http://www.microsoft.com/windowsazure/sdk/) - Note that later versions may be supported, but will require you to manually upgrade the ".Cloud" projects in the solution.
+ 5. (Optional, for unit tests) [xUnit for Visual Studio 2012](http://visualstudiogallery.msdn.microsoft.com/463c5987-f82b-46c8-a97e-b1cde42b9099)
+2. Clone it!
+
+ ```git clone git@github.com:NuGet/NuGetGallery.git```
+3. Build it!
+
+ ```
+ cd NuGetGallery
+ .\build
+ ```
+4. Set up the website in IIS Express!
+ 1. We highly recommend using IIS Express. Use the [Web Platform Installer](microsoft.com/web) to install it if you don't have it already (it comes with recent versions of VS and WebMatrix though)
+ 2. In an ADMIN powershell prompt, run the .\tools\Enable-LocalTestMe.ps1 file. It allows non-admins to host websites at: http://nuget.localtest.me, it configures an IIS Express site at that URL and creates a self-signed SSL certificate. For more information on localtest.me, check out [readme.localtest.me](readme.localtest.me)
+ 3. If you're having trouble, go to the Project Properties for the Website project, click on the Web tab and change the URL to localhost:port where _port_ is some port number above 1024.
+
+5. Create the Database!
+ 1. Open Visual Studio 2012
+ 2. Open the Package Manager Console window
+ 3. Ensure that the Default Project is set to `NuGetGallery`
+ 4. Open the NuGetGallery.sln solution from the root of this repository. ***Important:*** Make sure the Package Manager Console has been opened once before you open the solution. If the solution was already open, open the package manager console and then close and re-open the solution (from the file menu)
+ 5. Run the following command in the Package Manager Console:
+
+ ```
+ Update-Database
+ ```
+If this fails, you are likely to get more useful output by passing -Debug than -Verbose.
+<<<<<<< HEAD
+5. Set up the website in IIS Express!
+=======
+
+6. Set up the website in IIS Express!
+>>>>>>> origin/staging
+ 1. We highly recommend using IIS Express. Use the [Web Platform Installer](microsoft.com/web) to install it if you don't have it already (it comes with recent versions of VS and WebMatrix though)
+ 2. In an ADMIN powershell prompt, run the .\build\Enable-LocalTestMe.ps1 file. It allows non-admins to host websites at: http://nuget.localtest.me, it configures an IIS Express site at that URL and creates a self-signed SSL certificate. For more information on localtest.me, check out [readme.localtest.me](readme.localtest.me)
+ 3. If you're having trouble, go to the Project Properties for the Website project, click on the Web tab and change the URL to localhost:port where _port_ is some port number above 1024.
+
+7. Ensure the 'NuGetGallery' project (under the Frontend folder) is set to the Startup Project
+
+
+That's it! You should now be able to press Ctrl-F5 to run the site!
+
+## Contribute
+If you find a bug with the gallery, please visit the Issue tracker (https://github.com/NuGet/NuGetGallery/issues) and
+create an issue. If you're feeling generous, please search to see if the issue is already logged before creating a
+new one.
+
+When creating an issue, clearly explain
+* What you were trying to do.
+* What you expected to happen.
+* What actually happened.
+* Steps to reproduce the problem.
+
+Also include any information you think is relevant to reproducing the problem such as the browser version you used.
+Does it happen when you switch browsers. And so on.
+
+## Submit a patch
+Before starting work on an issue, either create an issue or comment on an existing issue to ensure that we're all
+communicating.
+
+To contribute to the gallery, make sure to create a fork first. Make your changes in the fork following
+the Git Workflow. When you are done with your changes, send us a pull request.
+
+## Copyright and License
+Copyright 2011 Outercurve Foundation
+
+Licensed under the Apache License, Version 2.0 (the "License"); you may not use this work except in compliance with
+the License. You may obtain a copy of the License in the LICENSE file, or at:
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
+an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
+specific language governing permissions and limitations under the License.
+
+## The Git Workflow
+
+This is the Git workflow we're currently using:
+
+### Setting up
+
+1. Clone and checkout the following branches (to make sure local copies are made): 'dev', 'dev-start'
+
+### When starting a new feature/unit of work.
+
+1. __Pull the latest.__
+ Begin by pulling to make sure you are up-to-date before creating a branch to do your work
+ This assumes you have no local commits that haven't yet been pushed (i.e., that you were
+ previously up-to-date with origin).
+
+ git checkout dev-start
+ git pull dev-start
+
+2. __Create a topic branch to do your work.__
+ You must work in topic branches, in order to help us keep our features isolated and easily moved between branches.
+ Our policy is to start all topic branches off of the 'dev-start' branch.
+ Branch names should use the following format '[user]-[bugnumber]-[shortdescription]'. If there is no bug yet,
+ create one and assign it to yourself!
+
+ git checkout dev-start
+ git checkout -b anurse-123-makesuckless
+
+3. __Do your work.__
+ Now, do your work using the following highly accurate and efficient algorithm :)
+
+ 1. Make changes.
+ 2. Test your changes (you're practicing TDD, right?)
+ 3. Add your changes to git's index.
+
+ git add -A
+
+ 4. Commit your changes.
+
+ git commit -m "<description of work>"
+
+ 5. if (moreWorkToDo) go to #3.1 else go to #4.
+
+4. __Start a code review.__
+ Start a code review by pushing your branch up to GitHub (```git push origin anurse-123-makesuckless```) and
+ creating a Pull Request from your branch to ***dev***. Wait for at least someone on the team to respond with: ":shipit:" (that's called the
+ "Ship-It Squirrel" and you can put it in your own comments by typing ```:shipit:```).
+
+5. __Merge your changes in to dev.__
+ Click the bright green "Merge" button on your pull request! **NOTE: DO NOT DELETE THE TOPIC BRANCH!!**
+
+ If there isn't a bright green button... well, you'll have to do some more complicated merging:
+
+ git checkout dev
+ git pull origin dev
+ git merge anurse-123-makesuckless
+ ... resolve conflicts ...
+ git push origin dev
+
+6. __Be ready to guide your change through QA, Staging and Master__
+ Your change will make its way through the QA, Staging and finally Master branches as it's deployed to the various environments. Be prepared to fix additional bugs!
+
+**NOTE: DO NOT DELETE THE TOPIC BRANCH!!**
View
19 ops/Modules/NuGetOps/NuGetOps.psm1
@@ -24,6 +24,25 @@ if(Test-Path $SDKParent) {
$AzureSDKRoot = (dir $SDKParent | sort Name -desc | select -first 1).FullName
}
+# Find the NuGet Internal repo
+$Global:ConfigRoot = $env:NUGET_CONFIG_ROOT
+$guessedRoot = Join-Path (Split-Path -Parent $Global:RepoRoot) "NuGetMicrosoft\NuGetInternal\Config"
+if(!$Global:ConfigRoot) {
+ Write-Host "NUGET_CONFIG_ROOT not set, searching for repo..."
+ $Global:ConfigRoot = $guessedRoot
+}
+
+if(!(Test-Path $Global:ConfigRoot)) {
+ $Global:ConfigRoot = $null;
+ Write-Warning "Could not find NuGet Configuration Files Path."
+ Write-Warning "If you put it in $guessedRoot, we'll find it automatically"
+ Write-Warning "Otherwise, set the NUGET_CONFIG_ROOT environment variable to the root path"
+ Write-Warning "If you are not deploying NuGet.org, set NUGET_CONFIG_ROOT to a path that contains CSCFG files for your service"
+}
+if($Global:ConfigRoot -and (@(dir "$Global:ConfigRoot\*.cscfg").Length -eq 0)) {
+ Write-Warning "Found no CSCFG files in $($Global:ConfigRoot)"
+}
+
if(!$AzureSDKRoot) {
Write-Warning "Couldn't find the Azure SDK. Some commands may not work."
} else {
View
10 ops/Modules/NuGetOps/Private/ParseConfigurationSettings.ps1
@@ -0,0 +1,10 @@
+function ParseConfigurationSettings($file) {
+ $xml = [xml](cat $file)
+ $role = $xml.ServiceConfiguration.Role | Select-Object -First 1
+
+ $hash = @{}
+ $role.ConfigurationSettings.Setting | ForEach-Object {
+ $hash[$_.name] = $_.value
+ }
+ $hash
+}
View
33 ops/Modules/NuGetOps/Public/Get-Configuration.ps1
@@ -0,0 +1,33 @@
+<#
+.SYNOPSIS
+Lists the available configuration files for a service
+
+.PARAMETER Type
+The type of service to list configurations for
+#>
+function Get-Configuration {
+ [CmdletBinding(SupportsShouldProcess=$true, ConfirmImpact="high")]
+ param(
+ [Parameter(Mandatory=$false, Position=0)][string]$Type
+ )
+
+ if(!$ConfigRoot) {
+ return;
+ }
+
+ dir "$ConfigRoot\*.cscfg" | ForEach-Object {
+ $match = [Regex]::Match($_.Name, "(?<type>.*)\.(?<env>.*)\.cscfg")
+ if($match.Success) {
+ $cfg = New-Object PSCustomObject
+ Add-Member -InputObject $cfg -NotePropertyMembers @{
+ "Type" = $match.Groups["type"].Value;
+ "Environment" = $match.Groups["env"].Value;
+ "File" = $_.FullName
+ }
+ $cfg
+ }
+ } | Where-Object {
+ (([String]::IsNullOrEmpty($Type)) -or ($Type -eq $_.Type)) -and
+ (($CurrentEnvironment -eq $null) -or ($CurrentEnvironment.Name -eq $_.Environment))
+ }
+}
View
25 ops/Modules/NuGetOps/Public/Get-ConfigurationSettings.ps1
@@ -0,0 +1,25 @@
+<#
+.SYNOPSIS
+Lists the available configuration files for a service
+
+.PARAMETER Type
+The type of service to list configurations settings for
+#>
+function Get-ConfigurationSettings {
+ [CmdletBinding(SupportsShouldProcess=$true, ConfirmImpact="high")]
+ param(
+ [Parameter(Mandatory=$true, Position=1)][string]$Type
+ )
+
+ if(!$ConfigRoot) {
+ return;
+ }
+
+ if(!$CurrentEnvironment) {
+ throw "Requires a current environment"
+ }
+
+ $Config = Get-Configuration -Type $Type | Select-Object -First 1
+
+ ParseConfigurationSettings $Config.File
+}
View
128 src/NuGetGallery.Backend.Cloud/NuGetGallery.Backend.Cloud.ccproj.orig
@@ -0,0 +1,128 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+<<<<<<< HEAD
+ <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProductVersion>2.2</ProductVersion>
+ <ProjectGuid>1d0164b6-92d4-455a-ac68-c30b61733748</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>NuGetGallery.Backend.Cloud</RootNamespace>
+ <AssemblyName>NuGetGallery.Backend.Cloud</AssemblyName>
+ <StartDevelopmentStorage>True</StartDevelopmentStorage>
+ <Name>NuGetGallery.Backend.Cloud</Name>
+ <UseWebProjectPorts>True</UseWebProjectPorts>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\NuGetGallery.Backend\NuGetGallery.Backend.csproj">
+ <Name>NuGetGallery.Backend</Name>
+ <Project>{7F92C174-5310-4090-A6A3-3CC7C67C19D6}</Project>
+ <Private>True</Private>
+ <RoleType>Worker</RoleType>
+ <RoleName>NuGetGallery.Backend</RoleName>
+ <UpdateDiagnosticsConnectionStringOnPublish>True</UpdateDiagnosticsConnectionStringOnPublish>
+ </ProjectReference>
+ </ItemGroup>
+ <!-- Items for the project -->
+ <ItemGroup>
+ <ServiceDefinition Include="ServiceDefinition.csdef" />
+ <ServiceConfiguration Include="ServiceConfiguration.Local.cscfg" />
+ </ItemGroup>
+ <ItemGroup>
+ <Folder Include="NuGetGallery.BackendContent\" />
+ </ItemGroup>
+ <ItemGroup>
+ <Content Include="NuGetGallery.BackendContent\diagnostics.wadcfg">
+ <SubType>Content</SubType>
+ </Content>
+ </ItemGroup>
+ <!-- Import the target files for this project template -->
+ <PropertyGroup>
+ <VisualStudioVersion Condition=" '$(VisualStudioVersion)' == '' ">10.0</VisualStudioVersion>
+ <CloudExtensionsDir Condition=" '$(CloudExtensionsDir)' == '' ">$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v$(VisualStudioVersion)\Windows Azure Tools\2.2\</CloudExtensionsDir>
+ </PropertyGroup>
+ <Import Project="$(CloudExtensionsDir)Microsoft.WindowsAzure.targets" />
+ <Import Project="$(MSBuildProjectDirectory)\..\..\build\NuGetGallery.Cloud.targets" />
+</Project>
+=======
+ <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProductVersion>2.2</ProductVersion>
+ <ProjectGuid>1d0164b6-92d4-455a-ac68-c30b61733748</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>NuGetGallery.Backend.Cloud</RootNamespace>
+ <AssemblyName>NuGetGallery.Backend.Cloud</AssemblyName>
+ <StartDevelopmentStorage>True</StartDevelopmentStorage>
+ <Name>NuGetGallery.Backend.Cloud</Name>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\NuGetGallery.Backend\NuGetGallery.Backend.csproj">
+ <Name>NuGetGallery.Backend</Name>
+ <Project>{7F92C174-5310-4090-A6A3-3CC7C67C19D6}</Project>
+ <Private>True</Private>
+ <RoleType>Worker</RoleType>
+ <RoleName>NuGetGallery.Backend</RoleName>
+ <UpdateDiagnosticsConnectionStringOnPublish>True</UpdateDiagnosticsConnectionStringOnPublish>
+ </ProjectReference>
+ </ItemGroup>
+ <!-- Items for the project -->
+ <ItemGroup>
+ <ServiceDefinition Include="ServiceDefinition.csdef" />
+ <ServiceConfiguration Include="ServiceConfiguration.Local.cscfg" />
+ </ItemGroup>
+ <ItemGroup>
+ <Folder Include="NuGetGallery.BackendContent\" />
+ </ItemGroup>
+ <ItemGroup>
+ <Content Include="NuGetGallery.BackendContent\diagnostics.wadcfg">
+ <SubType>Content</SubType>
+ </Content>
+ </ItemGroup>
+ <!-- Import the target files for this project template -->
+ <PropertyGroup>
+ <VisualStudioVersion Condition=" '$(VisualStudioVersion)' == '' ">10.0</VisualStudioVersion>
+ <CloudExtensionsDir Condition=" '$(CloudExtensionsDir)' == '' ">$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v$(VisualStudioVersion)\Windows Azure Tools\2.2\</CloudExtensionsDir>
+ </PropertyGroup>
+ <Import Project="$(CloudExtensionsDir)Microsoft.WindowsAzure.targets" />
+ <Import Project="$(MSBuildProjectDirectory)\..\..\build\NuGetGallery.Cloud.targets" />
+</Project>
+>>>>>>> qa
View
284 src/NuGetGallery.Operations/Tasks/HandleQueuedPackageEditsTask.cs.orig
@@ -0,0 +1,284 @@
+using System;
+using System.Collections.Generic;
+using System.Data;
+using System.Data.Entity;
+using System.Data.Entity.Infrastructure;
+using System.Data.EntityClient;
+using System.Data.Objects;
+using System.IO;
+using System.Linq;
+using System.Security.Cryptography;
+using System.Threading;
+using Microsoft.WindowsAzure.Storage.Blob;
+using NuGet;
+using NuGetGallery.Packaging;
+
+namespace NuGetGallery.Operations.Tasks
+{
+ [Command("handlequeuededits", "Handle Queued Package Edits", AltName = "hqe", MaxArgs = 0)]
+ public class HandleQueuedPackageEditsTask : DatabaseAndStorageTask
+ {
+ static int[] SleepTimes = { 50, 750, 1500, 2500, 3750, 5250, 7000, 9000 };
+
+ [Option("Set this option to ignore the tried count and process ALL edits", AltName = "a")]
+ public bool IncludePreviouslyFailedEdits { get; set; }
+
+ public override void ExecuteCommand()
+ {
+ // Work to do:
+ // 0) Find Pending Edits in DB that have been attempted less than 3 times
+ // 1) Backup all old NUPKGS
+ // 2) Generate all new NUPKGs (in place), and tell gallery the edit is completed
+ var connectionString = ConnectionString.ConnectionString;
+
+ // We group edits together by their package key and process them together - this is a read-only operation
+ var entitiesContext = new EntitiesContext(connectionString, readOnly: true);
+<<<<<<< HEAD
+ IQueryable<PackageEdit> allEdits = entitiesContext.Set<PackageEdit>();
+ if(!IncludePreviouslyFailedEdits) {
+ allEdits = allEdits.Where(pe => pe.TriedCount < 3);
+ }
+ var editsPerPackage = allEdits.GroupBy(pe => pe.PackageKey);
+=======
+ var editsPerPackage = entitiesContext.Set<PackageEdit>()
+ .GroupBy(pe => pe.PackageKey);
+>>>>>>> origin/tilovell/1541-betterFailedEditUX
+
+ // Now that we have our list of packages with pending edits, we'll process the pending edits for each
+ // Note that we're not doing editing in parallel because
+ // a) any particular blob may use a large amount of memory to process. Let's not multiply that!
+ // b) we don't want multithreaded usage of the entitiesContext (and its implied transactions)!
+ foreach (IGrouping<int, PackageEdit> editsGroup in editsPerPackage)
+ {
+ if (editsGroup.Any((pe => pe.TriedCount < 3)))
+ {
+ ProcessPackageEdits(editsGroup.Key, editsGroup);
+ }
+ }
+ }
+
+ private void ProcessPackageEdits(int packageKey, IEnumerable<PackageEdit> editsToDelete)
+ {
+ // Create a fresh entities context so that we work in isolation
+ var entitiesContext = new EntitiesContext(ConnectionString.ConnectionString, readOnly: false);
+
+<<<<<<< HEAD
+ // Get the list of edits for this package
+ // Do edit with a 'most recent edit to this package wins - other edits are deleted' strategy.
+ IQueryable<PackageEdit> editSet = entitiesContext.Set<PackageEdit>();
+ if (IncludePreviouslyFailedEdits)
+ {
+ editSet = editSet.Where(pe => pe.PackageKey == packageKey);
+ }
+ else
+ {
+ editSet = editSet.Where(pe => pe.PackageKey == packageKey && pe.TriedCount < 3);
+ }
+
+ var editsForThisPackage = editSet
+=======
+ // Get the most recent edit for this package
+ var edit = entitiesContext.Set<PackageEdit>()
+ .Where(pe => pe.PackageKey == packageKey && pe.TriedCount < 3)
+>>>>>>> origin/tilovell/1541-betterFailedEditUX
+ .Include(pe => pe.Package)
+ .Include(pe => pe.Package.PackageRegistration)
+ .Include(pe => pe.User)
+ .OrderByDescending(pe => pe.Timestamp)
+ .First();
+
+ // List of Work to do:
+ // 1) Backup old blob, if the original has not been backed up yet
+ // 2) Downloads blob, create new NUPKG locally
+ // 3) Upload blob
+ // 4) Update the database
+ var blobClient = StorageAccount.CreateCloudBlobClient();
+ var packagesContainer = Util.GetPackagesBlobContainer(blobClient);
+
+ var latestPackageFileName = Util.GetPackageFileName(edit.Package.PackageRegistration.Id, edit.Package.NormalizedVersion);
+ var originalPackageFileName = Util.GetBackupOfOriginalPackageFileName(edit.Package.PackageRegistration.Id, edit.Package.NormalizedVersion);
+
+ var originalPackageBackupBlob = packagesContainer.GetBlockBlobReference(originalPackageFileName);
+ var latestPackageBlob = packagesContainer.GetBlockBlobReference(latestPackageFileName);
+
+ var edits = new List<Action<ManifestMetadata>>
+ {
+ (m) => { m.Authors = edit.Authors; },
+ (m) => { m.Copyright = edit.Copyright; },
+ (m) => { m.Description = edit.Description; },
+ (m) => { m.IconUrl = edit.IconUrl; },
+ (m) => { m.LicenseUrl = edit.LicenseUrl; },
+ (m) => { m.ProjectUrl = edit.ProjectUrl; },
+ (m) => { m.ReleaseNotes = edit.ReleaseNotes; },
+ (m) => { m.RequireLicenseAcceptance = edit.RequiresLicenseAcceptance; },
+ (m) => { m.Summary = edit.Summary; },
+ (m) => { m.Title = edit.Title; },
+ (m) => { m.Tags = edit.Tags; },
+ };
+
+ Log.Info(
+ "Processing Edit Key={0}, PackageId={1}, Version={2}, User={3}",
+ edit.Key,
+ edit.Package.PackageRegistration.Id,
+ edit.Package.NormalizedVersion,
+ edit.User.Username);
+
+ if (!WhatIf)
+ {
+ edit.TriedCount += 1;
+ int nr = entitiesContext.SaveChanges();
+ if (nr != 1)
+ {
+ throw new Exception(
+ String.Format("Something went terribly wrong, only one entity should be updated but actually {0} entities were updated", nr));
+ }
+ }
+
+ try
+ {
+ ArchiveOriginalPackageBlob(originalPackageBackupBlob, latestPackageBlob);
+ using (var readWriteStream = new MemoryStream())
+ {
+ // Download to memory
+ CloudBlockBlob downloadSourceBlob = WhatIf ? latestPackageBlob : originalPackageBackupBlob;
+ Log.Info("Downloading original package blob to memory {0}", downloadSourceBlob.Name);
+ downloadSourceBlob.DownloadToStream(readWriteStream);
+
+ // Rewrite in memory
+ Log.Info("Rewriting nupkg package in memory", downloadSourceBlob.Name);
+ NupkgRewriter.RewriteNupkgManifest(readWriteStream, edits);
+
+ // Get updated hash code, and file size
+ Log.Info("Computing updated hash code of memory stream");
+ var newPackageFileSize = readWriteStream.Length;
+ var hashAlgorithm = HashAlgorithm.Create("SHA512");
+ byte[] hashBytes = hashAlgorithm.ComputeHash(readWriteStream.GetBuffer());
+ var newHash = Convert.ToBase64String(hashBytes);
+
+ if (!WhatIf)
+ {
+ // Snapshot the blob
+ var blobSnapshot = latestPackageBlob.CreateSnapshot();
+
+ // Build up the changes in the entities context
+ edit.Apply(hashAlgorithm: "SHA512", hash: newHash, packageFileSize: newPackageFileSize);
+ foreach (var eachEdit in editsToDelete)
+ {
+ entitiesContext.DeleteOnCommit(eachEdit);
+ }
+
+ // Upload the blob before doing SaveChanges(). If blob update fails, we won't do SaveChanges() and the edit can be retried.
+ // If SaveChanges() fails we can undo the blob upload.
+ try
+ {
+ Log.Info("Uploading blob from memory {0}", latestPackageBlob.Name);
+ readWriteStream.Position = 0;
+ latestPackageBlob.UploadFromStream(readWriteStream);
+ }
+ catch (Exception e)
+ {
+ Log.Error("(error) - package edit blob update failed.");
+ Log.ErrorException("(exception)", e);
+ Log.Error("(note) - blob snapshot URL = " + blobSnapshot.Uri);
+ throw; // To handler block that will record error in DB
+ }
+
+ try
+ {
+ // SaveChanges tries to commit changes to DB
+ entitiesContext.SaveChanges();
+ }
+ catch (Exception e)
+ {
+ // Commit changes to DB probably failed.
+ // Since our blob update wasn't part of the transaction (and doesn't AFAIK have a 'commit()' operator we can utilize for the type of blobs we are using)
+ // try, (single attempt) to roll back the blob update by restoring the previous snapshot.
+ Log.Error("(error) - package edit DB update failed. Trying to roll back the blob to its previous snapshot.");
+ Log.ErrorException("(exception)", e);
+ Log.Error("(note) - blob snapshot URL = " + blobSnapshot.Uri);
+ try
+ {
+ latestPackageBlob.StartCopyFromBlob(blobSnapshot);
+ }
+ catch (Exception e2)
+ {
+ // If blob rollback fails it is not be the end of the world
+ // - the package metadata mismatches the edit now,
+ // but there should still an edit in the queue, waiting to be rerun and put everything back in synch.
+ Log.Error("(error) - rolling back the package blob to its previous snapshot failed.");
+ Log.ErrorException("(exception)", e2);
+ Log.Error("(note) - blob snapshot URL = " + blobSnapshot.Uri);
+ }
+
+ throw; // To handler block that will record error in DB
+ }
+ }
+ }
+ }
+ catch (Exception e)
+ {
+ if (!WhatIf)
+ {
+ try
+ {
+ Log.Info("Storing the error on package edit with key {0}", edit.Key);
+
+ // Try to record the error into the PackageEdit database record
+ // so that we can actually diagnose failures.
+ // This must be done on a fresh context to ensure no conflicts.
+ var errorContext = new EntitiesContext(ConnectionString.ConnectionString, readOnly: false);
+ var errorEdit = errorContext.Set<PackageEdit>().Where(pe => pe.Key == edit.Key).FirstOrDefault();
+
+ if (errorEdit != null)
+ {
+ errorEdit.LastError = string.Format("{0} : {1}", e.GetType(), e);
+ errorContext.SaveChanges();
+ }
+ else
+ {
+ Log.Info("The package edit with key {0} couldn't be found. It was likely canceled and deleted.", edit.Key);
+ }
+ }
+ catch (Exception errorException)
+ {
+ Log.ErrorException("(error) - couldn't save the last error on the edit that was being applied.", errorException);
+ }
+ }
+ }
+ }
+
+ /// <summary>
+ /// Creates an archived copy of the original package blob if it doesn't already exist.
+ /// </summary>
+ private void ArchiveOriginalPackageBlob(CloudBlockBlob originalPackageBlob, CloudBlockBlob latestPackageBlob)
+ {
+ // Copy the blob to backup only if it isn't already successfully copied
+ if ((!originalPackageBlob.Exists()) || (originalPackageBlob.CopyState != null && originalPackageBlob.CopyState.Status != CopyStatus.Success))
+ {
+ if (!WhatIf)
+ {
+ Log.Info("Backing up blob: {0} to {1}", latestPackageBlob.Name, originalPackageBlob.Name);
+ originalPackageBlob.StartCopyFromBlob(latestPackageBlob);
+ CopyState state = originalPackageBlob.CopyState;
+
+ for (int i = 0; (state == null || state.Status == CopyStatus.Pending) && i < SleepTimes.Length; i++)
+ {
+ Log.Info("(sleeping for a copy completion)");
+ Thread.Sleep(SleepTimes[i]);
+ originalPackageBlob.FetchAttributes(); // To get a refreshed CopyState
+
+ //refresh state
+ state = originalPackageBlob.CopyState;
+ }
+
+ if (state.Status != CopyStatus.Success)
+ {
+ string msg = string.Format("Blob copy failed: CopyState={0}", state.StatusDescription);
+ Log.Error("(error) " + msg);
+ throw new BlobBackupFailedException(msg);
+ }
+ }
+ }
+ }
+ }
+}
View
3  src/NuGetGallery.Operations/Tasks/ReplicatePackageStatisticsTask.cs
@@ -104,7 +104,8 @@ SELECT TOP(@top)
FROM PackageStatistics
INNER JOIN Packages ON PackageStatistics.PackageKey = Packages.[Key]
INNER JOIN PackageRegistrations ON PackageRegistrations.[Key] = Packages.PackageRegistrationKey
- WHERE PackageStatistics.[Key] > @originalKey
+ WHERE PackageStatistics.[Key] > @originalKey
+ ORDER BY PackageStatistics.[Key]
";
SqlCommand command = new SqlCommand(sql, connection);
View
4 src/NuGetGallery/Controllers/ApiController.cs
@@ -118,8 +118,8 @@ public partial class ApiController : AppController
DependentPackage = Request.Headers["NuGet-DependentPackage"],
ProjectGuids = Request.Headers["NuGet-ProjectGuids"],
};
-
- PackageService.AddDownloadStatistics(stats);
+ //Temporarily disable stats.
+ // PackageService.AddDownloadStatistics(stats);
}
catch (ReadOnlyModeException)
{
View
80 src/NuGetGallery/ViewModels/ReportAbuseViewModel.cs.orig
@@ -0,0 +1,80 @@
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.ComponentModel;
+using System.ComponentModel.DataAnnotations;
+using System.Web.Mvc;
+using NuGetGallery.Infrastructure;
+
+namespace NuGetGallery
+{
+ public enum ReportPackageReason
+ {
+ [Description("Other")]
+ Other,
+
+ [Description("The package has a bug/failed to install")]
+ HasABugOrFailedToInstall,
+
+ [Description("The package contains malicious code")]
+ ContainsMaliciousCode,
+
+ [Description("The package violates a license I own")]
+ ViolatesALicenseIOwn,
+
+ [Description("The package owner is fraudulently claiming authorship")]
+ IsFraudulent,
+
+ [Description("The package contains private/confidential data")]
+ ContainsPrivateAndConfidentialData,
+
+ [Description("The package was published as the wrong version")]
+ PublishedWithWrongVersion,
+
+ [Description("The package was not intended to be published publically on nuget.org")]
+ ReleasedInPublicByAccident,
+ }
+
+ public class ReportAbuseViewModel
+ {
+ public static readonly string NoReasonSpecifiedText = "Select a reason";
+
+ public string PackageId { get; set; }
+ public string PackageVersion { get; set; }
+
+ [Display(Name = "Contacted Owner")]
+ public bool AlreadyContactedOwner { get; set; }
+
+ [NotEqual(ReportPackageReason.HasABugOrFailedToInstall, ErrorMessage = "Unfortunately we cannot provide support for bugs in NuGet Packages. Please contact owner(s) for assistance.")]
+ [Required(ErrorMessage = "You must select a reason for reporting the package")]
+ [Display(Name = "Reason")]
+ public ReportPackageReason? Reason { get; set; }
+
+<<<<<<< HEAD
+=======
+ [Display(Name = "Send me a copy")]
+ public bool CopySender { get; set; }
+
+>>>>>>> 1be02a7... Merge branch 'master' of https://github.com/NuGet/NuGetGallery
+ [Required(ErrorMessage = "Please enter a message.")]
+ [AllowHtml]
+ [StringLength(4000)]
+ [Display(Name = "Abuse Report")]
+ public string Message { get; set; }
+
+ [Required(ErrorMessage = "Please enter your email address.")]
+ [StringLength(4000)]
+ [Display(Name = "Your Email Address")]
+ //[DataType(DataType.EmailAddress)] - does not work with client side validation
+ [RegularExpression(RegisterViewModel.EmailValidationRegex,
+ ErrorMessage = "This doesn't appear to be a valid email address.")]
+ public string Email { get; set; }
+
+ public bool ConfirmedUser { get; set; }
+
+ public IEnumerable<ReportPackageReason> ReasonChoices { get; set; }
+
+ public ReportAbuseViewModel()
+ {
+ }
+ }
+}
View
47 src/NuGetGallery/Views/Packages/ContactOwners.cshtml.orig
@@ -0,0 +1,47 @@
+@model ContactOwnersViewModel
+@{
+ ViewBag.Tab = "Packages";
+ var owners = Model.Owners.Flatten(@<text>@item.Username</text>);
+}
+
+<h1 class="page-heading">Contact the Owners of "@Model.PackageId"</h1>
+@if (Model.Owners.Any())
+{
+ <p class="message">
+ By submitting this form, you agree to <em>disclose your email address</em>
+ to the package owners listed below so they can reply to you.
+ </p>
+ using (Html.BeginForm())
+ {
+ <fieldset class="form">
+ <legend>Contact Owners</legend>
+ @Html.AntiForgeryToken()
+ <div class="form-field">
+ <label for="NotUsed">To</label>
+ <input name="NotUsed" type="text" value="@owners" disabled="disabled" />
+ </div>
+ <div class="form-field">
+ @Html.LabelFor(m => m.Message)
+ @Html.TextAreaFor(m => m.Message, 10, 50, null)
+ @Html.ValidationMessageFor(m => m.Message)
+ </div>
+<<<<<<< HEAD
+ <img src="@Url.Content("~/content/images/required.png")" alt="Blue border on left means required." />
+=======
+ <div class="form-field">
+ @Html.CheckBoxFor(m => m.CopySender)
+ @Html.LabelFor(m => m.CopySender, new { @class = "checkbox" })
+ </div>
+ <img src="@Url.Content("~/Content/images/required.png")" alt="Blue border on left means required." />
+>>>>>>> 1be02a7... Merge branch 'master' of https://github.com/NuGet/NuGetGallery
+ <input type="submit" value="Send" title="Send your message to the owners of '@Model.PackageId'" />
+ </fieldset>
+ }
+}
+else
+{
+ <p class="error message">
+ Sorry, the owners of this package do not allow contacting them through this form.
+ Try visiting the project home page for "@Model.PackageId" in order to contact the package owner.
+ </p>
+}
View
8 src/NuGetGallery/Views/Packages/DisplayPackage.cshtml
@@ -163,14 +163,14 @@
</fieldset>
}
}
- @if (Model.HasEditFailures)
+ @if (Model.IsLastEditFailed)
{
<p class="failed-edit-message">
Your last edit to this package was not successfully applied.
- You can <a href="@Url.EditPackage(Model.Id, Model.Version)>edit</a>
+ You can <a href="@Url.EditPackage(Model.Id, Model.Version)">edit</a>
the package and submit the edit again to retry the edit.
</p>
- }
+ }
@if (Model.Prerelease)
{
<p class="prerelease-message">
@@ -333,4 +333,4 @@
}
</tbody>
</table>
-</div>
+</div>
View
101 src/NuGetGallery/Views/Packages/ReportAbuse.cshtml.orig
@@ -0,0 +1,101 @@
+@using PoliteCaptcha
+@model ReportAbuseViewModel
+@{
+ ViewBag.Tab = "Packages";
+ string returnUrl = ViewData.ContainsKey(Constants.ReturnUrlViewDataKey) ? (string)ViewData[Constants.ReturnUrlViewDataKey] : Request.RawUrl;
+}
+
+<h1 class="page-heading">Report Abuse</h1>
+
+<p class="message">
+ <strong>Important: Please do not use this form to report a bug in a package you are using!</strong><br />
+ This form is for reporting <em>abusive</em> packages such as
+ packages containing <em>malicious code</em> or spam. If "@Model.PackageId" simply doesn't
+ work, or if you need help getting the package installed, please
+ <a href="@Url.Action(MVC.Packages.ContactOwners(Model.PackageId))" title="contact the owners">contact the owners instead.</a>
+</p>
+
+<p>Please provide a detailed abuse report. Include exactly what the package did, for example if you are reporting a package with a virus or malicious code,
+ <em>please provide evidence to support your claim!</em> We cannot delete packages without evidence that they exhibit malicious behavior.</p>
+
+@if (!Model.ConfirmedUser)
+{
+ <p>Note: if you are the owner of @Model.PackageId, please
+ <a href="@Url.LogOn(returnUrl)">sign in now before you complete this form.</a>
+ </p>
+}
+
+@using (Html.BeginForm())
+{
+ <fieldset id="report-abuse-form" class="form">
+ <legend>Report Abuse</legend>
+ @Html.AntiForgeryToken()
+ <div class="form-field">
+ @if (!Model.ConfirmedUser)
+ {
+ @Html.LabelFor(m => m.Email)
+ @Html.EditorFor(m => m.Email)
+ <span class="field-hint-message">Provide your email address so we can follow up with you.</span>
+ @Html.ValidationMessageFor(m => m.Email)
+ }
+ else
+ {
+ <input type="hidden" name="Email" value="test@example.com" />
+ }
+ </div>
+ <div id="form-field-reason" class="form-field">
+ @Html.LabelFor(m => m.Reason)
+ @Html.EnumDropDownListFor(m => m.Reason, Model.ReasonChoices, "<Choose a Reason>")
+ @Html.ValidationMessageFor(m => m.Reason)
+ </div>
+ <div class="form-field">
+ @Html.CheckBoxFor(m => m.AlreadyContactedOwner)
+ @Html.LabelFor(m => m.AlreadyContactedOwner, "Yes! I have already tried to contact the package owner about this problem.",
+ new Dictionary<string, object>
+ {
+ { "style", "display: inline" },
+ })<br/>
+ </div>
+ <div class="form-field">
+ @Html.LabelFor(m => m.Message, "Abuse Report")
+ <p>In addition to selecting the reason for reporting the package, you must provide details of the problem here.</p>
+ @Html.TextAreaFor(m => m.Message, 10, 50, null)
+ @Html.ValidationMessageFor(m => m.Message, null, new { id = "report-abuse-message" })
+ </div>
+<<<<<<< HEAD
+ <img src="@Url.Content("~/content/images/required.png")" alt="Blue border on left means required." />
+=======
+ <div class="form-field" >
+ @Html.CheckBoxFor(m => m.CopySender)
+ @Html.LabelFor(m => m.CopySender, new { @class = "checkbox" })
+ </div>
+ <img src="@Url.Content("~/Content/images/required.png")" alt="Blue border on left means required." />
+>>>>>>> 1be02a7... Merge branch 'master' of https://github.com/NuGet/NuGetGallery
+ @Html.SpamPreventionFields()
+ <input id="form-submit" type="submit" value="Report" title="Report '@Model.PackageId' for abuse" />
+ </fieldset>
+}
+
+@section BottomScripts {
+ @Html.SpamPreventionScript()
+ <script>
+ function reasonSelected() {
+ var $form = $('#Reason').parents('form');
+ var val = $(this).val();
+ if (val) {
+ $form.validate().element($('#Reason'));
+ }
+
+ if (val === 'HasABugOrFailedToInstall') {
+ $form.find("input, textarea, select").not('#form-field-reason *').attr('disabled', 'disabled');
+ } else {
+ $form.find("input, textarea, select").not('#form-field-reason').removeAttr('disabled');
+ }
+ }
+
+ $(function () {
+ $('#Reason').change(reasonSelected);
+ reasonSelected(); // Run once in case it starts with the bad selection
+ });
+ </script>
+}
View
58 src/NuGetGallery/Views/Packages/ReportMyPackage.cshtml.orig
@@ -0,0 +1,58 @@
+@using PoliteCaptcha
+@model ReportAbuseViewModel
+@{
+ ViewBag.Tab = "Packages";
+}
+
+<h1 class="page-heading">Contact Support About My Package</h1>
+
+<p>Please select the reason for contacting support about your package.</p>
+
+@using (Html.BeginForm())
+{
+ <fieldset id="report-abuse-form" class="form">
+ <legend>Contact Support</legend>
+ @Html.AntiForgeryToken()
+ <div class="form-field">
+ @if (!Model.ConfirmedUser)
+ {
+ @Html.LabelFor(m => m.Email)
+ @Html.EditorFor(m => m.Email)
+ <span class="field-hint-message">Provide your email address so we can follow up with you.</span>
+ @Html.ValidationMessageFor(m => m.Email)
+ }
+ else
+ {
+ <input type="hidden" name="Email" value="test@example.com" />
+ }
+ </div>
+ <div id="form-field-reason" class="form-field">
+ @Html.LabelFor(m => m.Reason)
+ @Html.EnumDropDownListFor(m => m.Reason, Model.ReasonChoices, "<Choose a Reason>")
+ @Html.ValidationMessageFor(m => m.Reason, null, new { @class = "block-validation-error" })
+ </div>
+ <div class="form-field">
+ @Html.LabelFor(m => m.Message, "Problem")
+ <p>In addition to selecting the reason for reporting the package, you <em>must</em> provide details of the problem.</p>
+ @Html.TextAreaFor(m => m.Message, 10, 50, null)
+ @Html.ValidationMessageFor(m => m.Message, null, new { id = "report-abuse-message" })
+ </div>
+<<<<<<< HEAD
+ <img src="@Url.Content("~/content/images/required.png")" alt="Blue border on left means required." />
+=======
+ <div class="form-field">
+ @Html.CheckBoxFor(m => m.CopySender)
+ @Html.LabelFor(m => m.CopySender, new { @class = "checkbox" })
+ </div>
+ <img src="@Url.Content("~/Content/images/required.png")" alt="Blue border on left means required." />
+>>>>>>> 1be02a7... Merge branch 'master' of https://github.com/NuGet/NuGetGallery
+ @Html.SpamPreventionFields()
+ <input type="submit" value="Report" title="Report your problem with '@Model.PackageId'" />
+ </fieldset>
+}
+
+@section BottomScripts {
+ <script src="@Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
+ <script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
+ @Html.SpamPreventionScript()
+}
View
6 tests/.nuget/NuGet.Config
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<configuration>
+ <solution>
+ <add key="disableSourceControlIntegration" value="true" />
+ </solution>
+</configuration>
View
153 tests/.nuget/NuGet.targets
@@ -0,0 +1,153 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">$(MSBuildProjectDirectory)\..\</SolutionDir>
+
+ <!-- Enable the restore command to run before builds -->
+ <RestorePackages Condition=" '$(RestorePackages)' == '' ">false</RestorePackages>
+
+ <!-- Property that enables building a package from a project -->
+ <BuildPackage Condition=" '$(BuildPackage)' == '' ">false</BuildPackage>
+
+ <!-- Determines if package restore consent is required to restore packages -->
+ <RequireRestoreConsent Condition=" '$(RequireRestoreConsent)' != 'false' ">true</RequireRestoreConsent>
+
+ <!-- Download NuGet.exe if it does not already exist -->
+ <DownloadNuGetExe Condition=" '$(DownloadNuGetExe)' == '' ">false</DownloadNuGetExe>
+ </PropertyGroup>
+
+ <ItemGroup Condition=" '$(PackageSources)' == '' ">
+ <!-- Package sources used to restore packages. By default, registered sources under %APPDATA%\NuGet\NuGet.Config will be used -->
+ <!-- The official NuGet package source (https://nuget.org/api/v2/) will be excluded if package sources are specified and it does not appear in the list -->
+ <!--
+ <PackageSource Include="https://nuget.org/api/v2/" />
+ <PackageSource Include="https://my-nuget-source/nuget/" />
+ -->
+ </ItemGroup>
+
+ <PropertyGroup Condition=" '$(OS)' == 'Windows_NT'">
+ <!-- Windows specific commands -->
+ <NuGetToolsPath>$([System.IO.Path]::Combine($(SolutionDir), ".nuget"))</NuGetToolsPath>
+ <PackagesConfig>$([System.IO.Path]::Combine($(ProjectDir), "packages.config"))</PackagesConfig>
+ <PackagesDir>$([System.IO.Path]::Combine($(SolutionDir), "packages"))</PackagesDir>
+ </PropertyGroup>
+
+ <PropertyGroup Condition=" '$(OS)' != 'Windows_NT'">
+ <!-- We need to launch nuget.exe with the mono command if we're not on windows -->
+ <NuGetToolsPath>$(SolutionDir).nuget</NuGetToolsPath>
+ <PackagesConfig>packages.config</PackagesConfig>
+ <PackagesDir>$(SolutionDir)packages</PackagesDir>
+ </PropertyGroup>
+
+ <PropertyGroup>
+ <!-- NuGet command -->
+ <NuGetExePath Condition=" '$(NuGetExePath)' == '' ">$(NuGetToolsPath)\nuget.exe</NuGetExePath>
+ <PackageSources Condition=" $(PackageSources) == '' ">@(PackageSource)</PackageSources>
+
+ <NuGetCommand Condition=" '$(OS)' == 'Windows_NT'">"$(NuGetExePath)"</NuGetCommand>
+ <NuGetCommand Condition=" '$(OS)' != 'Windows_NT' ">mono --runtime=v4.0.30319 $(NuGetExePath)</NuGetCommand>
+
+ <PackageOutputDir Condition="$(PackageOutputDir) == ''">$(TargetDir.Trim('\\'))</PackageOutputDir>
+
+ <RequireConsentSwitch Condition=" $(RequireRestoreConsent) == 'true' ">-RequireConsent</RequireConsentSwitch>
+ <!-- Commands -->
+ <RestoreCommand>$(NuGetCommand) install "$(PackagesConfig)" -source "$(PackageSources)" $(RequireConsentSwitch) -o "$(PackagesDir)"</RestoreCommand>
+ <BuildCommand>$(NuGetCommand) pack "$(ProjectPath)" -p Configuration=$(Configuration) -o "$(PackageOutputDir)" -symbols</BuildCommand>
+
+ <!-- We need to ensure packages are restored prior to assembly resolve -->
+ <BuildDependsOn Condition="$(RestorePackages) == 'true'">
+ RestorePackages;
+ $(BuildDependsOn);
+ </BuildDependsOn>
+
+ <!-- Make the build depend on restore packages -->
+ <BuildDependsOn Condition="$(BuildPackage) == 'true'">
+ $(BuildDependsOn);
+ BuildPackage;
+ </BuildDependsOn>
+ </PropertyGroup>
+
+ <Target Name="CheckPrerequisites">
+ <!-- Raise an error if we're unable to locate nuget.exe -->
+ <Error Condition="'$(DownloadNuGetExe)' != 'true' AND !Exists('$(NuGetExePath)')" Text="Unable to locate '$(NuGetExePath)'" />
+ <SetEnvironmentVariable EnvKey="VisualStudioVersion" EnvValue="$(VisualStudioVersion)" Condition=" '$(VisualStudioVersion)' != '' AND '$(OS)' == 'Windows_NT' " />
+ <!--
+ Take advantage of MsBuild's build dependency tracking to make sure that we only ever download nuget.exe once.
+ This effectively acts as a lock that makes sure that the download operation will only happen once and all
+ parallel builds will have to wait for it to complete.
+ -->
+ <MsBuild Targets="_DownloadNuGet" Projects="$(MSBuildThisFileFullPath)" Properties="Configuration=NOT_IMPORTANT" />
+ </Target>
+
+ <Target Name="_DownloadNuGet">
+ <DownloadNuGet OutputFilename="$(NuGetExePath)" Condition=" '$(DownloadNuGetExe)' == 'true' AND !Exists('$(NuGetExePath)')" />
+ </Target>
+
+ <Target Name="RestorePackages" DependsOnTargets="CheckPrerequisites">
+ <Exec Command="$(RestoreCommand)"
+ Condition="'$(OS)' != 'Windows_NT' And Exists('$(PackagesConfig)')" />
+
+ <Exec Command="$(RestoreCommand)"
+ LogStandardErrorAsError="true"
+ Condition="'$(OS)' == 'Windows_NT' And Exists('$(PackagesConfig)')" />
+ </Target>
+
+ <Target Name="BuildPackage" DependsOnTargets="CheckPrerequisites">
+ <Exec Command="$(BuildCommand)"
+ Condition=" '$(OS)' != 'Windows_NT' " />
+
+ <Exec Command="$(BuildCommand)"
+ LogStandardErrorAsError="true"
+ Condition=" '$(OS)' == 'Windows_NT' " />
+ </Target>
+
+ <UsingTask TaskName="DownloadNuGet" TaskFactory="CodeTaskFactory" AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v4.0.dll">
+ <ParameterGroup>
+ <OutputFilename ParameterType="System.String" Required="true" />
+ </ParameterGroup>
+ <Task>
+ <Reference Include="System.Core" />
+ <Using Namespace="System" />
+ <Using Namespace="System.IO" />
+ <Using Namespace="System.Net" />
+ <Using Namespace="Microsoft.Build.Framework" />
+ <Using Namespace="Microsoft.Build.Utilities" />
+ <Code Type="Fragment" Language="cs">
+ <![CDATA[
+ try {
+ OutputFilename = Path.GetFullPath(OutputFilename);
+
+ Log.LogMessage("Downloading latest version of NuGet.exe...");
+ WebClient webClient = new WebClient();
+ webClient.DownloadFile("https://nuget.org/nuget.exe", OutputFilename);
+
+ return true;
+ }
+ catch (Exception ex) {
+ Log.LogErrorFromException(ex);
+ return false;
+ }
+ ]]>
+ </Code>
+ </Task>
+ </UsingTask>
+
+ <UsingTask TaskName="SetEnvironmentVariable" TaskFactory="CodeTaskFactory" AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v4.0.dll">
+ <ParameterGroup>
+ <EnvKey ParameterType="System.String" Required="true" />
+ <EnvValue ParameterType="System.String" Required="true" />
+ </ParameterGroup>
+ <Task>
+ <Using Namespace="System" />
+ <Code Type="Fragment" Language="cs">
+ <![CDATA[
+ try {
+ Environment.SetEnvironmentVariable(EnvKey, EnvValue, System.EnvironmentVariableTarget.Process);
+ }
+ catch {
+ }
+ ]]>
+ </Code>
+ </Task>
+ </UsingTask>
+</Project>
View
31 tests/Local.testsettings
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<TestSettings name="Local" id="62f583f0-2eca-4773-bed0-474a13faad76" xmlns="http://microsoft.com/schemas/VisualStudio/TeamTest/2010">
+ <Description>These are default test settings for a local test run.</Description>
+ <Deployment userDeploymentRoot="." useDefaultDeploymentRoot="false">
+ <DeploymentItem filename=".nuget\NuGet.Config" />
+ <DeploymentItem filename=".nuget\NuGet.exe" />
+ <DeploymentItem filename=".nuget\NuGet.targets" />
+ </Deployment>
+ <NamingScheme baseName="TestResults" appendTimeStamp="false" useDefault="false" />
+ <Execution>
+ <TestTypeSpecific>
+ <UnitTestRunConfig testTypeId="13cdc9d9-ddb5-4fa4-a97d-d965ccfc6d4b">
+ <AssemblyResolution>
+ <TestDirectory useLoadContext="true" />
+ </AssemblyResolution>
+ </UnitTestRunConfig>
+ <WebTestRunConfiguration testTypeId="4e7599fa-5ecb-43e9-a887-cd63cf72d207">
+ <Browser name="Internet Explorer 9.0" MaxConnections="6">
+ <Headers>
+ <Header name="User-Agent" value="Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)" />
+ <Header name="Accept" value="*/*" />
+ <Header name="Accept-Language" value="{{$IEAcceptLanguage}}" />
+ <Header name="Accept-Encoding" value="GZIP" />
+ </Headers>
+ </Browser>
+ </WebTestRunConfiguration>
+ </TestTypeSpecific>
+ <AgentRule name="LocalMachineDefaultRole">
+ </AgentRule>
+ </Execution>
+</TestSettings>
View
6 tests/NuGetGallery.Facts/Controllers/ApiControllerFacts.cs
@@ -336,7 +336,8 @@ public class TheGetPackageAction
var actionResult = new EmptyResult();
var controller = new TestableApiController(MockBehavior.Strict);
controller.MockPackageService.Setup(x => x.FindPackageByIdAndVersion(PackageId, "1.0.1", false)).Returns(package);
- controller.MockPackageService.Setup(x => x.AddDownloadStatistics(It.IsAny<PackageStatistics>())).Verifiable();
+ //Disable it temporarily as AddDownloadStats is not being invoked currently
+ // controller.MockPackageService.Setup(x => x.AddDownloadStatistics(It.IsAny<PackageStatistics>())).Verifiable();
controller.MockPackageFileService.Setup(s => s.CreateDownloadPackageActionResultAsync(HttpRequestUrl, PackageId, package.NormalizedVersion))
.Returns(Task.FromResult<ActionResult>(actionResult))
.Verifiable();
@@ -410,7 +411,8 @@ public class TheGetPackageAction
var actionResult = new EmptyResult();
var controller = new TestableApiController(MockBehavior.Strict);
controller.MockPackageService.Setup(x => x.FindPackageByIdAndVersion(PackageId, "", false)).Returns(package);
- controller.MockPackageService.Setup(x => x.AddDownloadStatistics(It.IsAny<PackageStatistics>())).Verifiable();
+ //Disable it temporarily as AddDownloadStats is not being invoked currently
+ // controller.MockPackageService.Setup(x => x.AddDownloadStatistics(It.IsAny<PackageStatistics>())).Verifiable();
controller.MockPackageFileService.Setup(s => s.CreateDownloadPackageActionResultAsync(HttpRequestUrl, PackageId, package.NormalizedVersion))
.Returns(Task.FromResult<ActionResult>(actionResult))
View
6 tests/NuGetGallery.FunctionalTests.Fluent/App.config
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<configuration>
+ <startup>
+ <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
+ </startup>
+</configuration>
View
128 tests/NuGetGallery.FunctionalTests.Fluent/EditPackageAsPartOfUploadTest.cs
@@ -0,0 +1,128 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Net;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+using NuGetGallery.FunctionTests.Helpers;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using FluentAutomation;
+
+namespace NuGetGallery.FunctionalTests.Fluent
+{
+
+ [TestClass]
+ public class EditPackageAsPartOfUploadTest : NuGetFluentTest
+ {
+ public EditPackageAsPartOfUploadTest()
+ {
+ FluentAutomation.SeleniumWebDriver.Bootstrap();
+ }
+
+ [TestMethod]
+ [Description("Edit every possible metadata field of the package as part of upload.")]
+ public void EditPackageAsPartOfUpload()
+ {
+ // Use the same package name, but force the version to be unique.
+ string packageName = "NuGetGallery.FunctionalTests.Fluent.EditPackageAsPartOfUploadTest";
+ string ticks = DateTime.Now.Ticks.ToString();
+ string version = new System.Version(ticks.Substring(0, 6) + "." + ticks.Substring(6, 6) + "." + ticks.Substring(12, 6)).ToString();
+ string newPackageLocation = PackageCreationHelper.CreatePackage(packageName, version);
+
+ // Log on using the test account.
+ I.LogOn(EnvironmentSettings.TestAccountName, EnvironmentSettings.TestAccountPassword);
+
+ // Navigate to the upload page.
+ I.UploadPackageUsingUI(newPackageLocation);
+
+ // Edit the package.
+ I.Click("#Edit_VersionTitleButton");
+ string newTitle = String.Format("This title is accurate as of {0}.", DateTime.Now.ToString("F"));
+ I.Enter(newTitle).In("#Edit_VersionTitle");
+
+ I.Click("#Edit_DescriptionButton");
+ string newDescription = String.Format("This description is accurate as of {0}.", DateTime.Now.ToString("F"));
+ I.Enter(newDescription).In("#Edit_Description");
+
+ I.Click("#Edit_SummaryButton");
+ string newSummary = String.Format("This summary is accurate as of {0}.", DateTime.Now.ToString("F"));
+ I.Enter(newSummary).In("#Edit_Summary");
+
+ I.Click("#Edit_IconUrlButton");
+ string newIconUrl = String.Format("http://microsoft.com/IconUrl/{0}", DateTime.Now.ToString("FFFFFFF"));
+ I.Enter(newIconUrl).In("#Edit_IconUrl");
+
+ I.Click("#Edit_ProjectUrlButton");
+ string newHomePageUrl = String.Format("http://microsoft.com/HomePageUrl/{0}", DateTime.Now.ToString("FFFFFFF"));
+ I.Enter(newHomePageUrl).In("#Edit_ProjectUrl");
+
+ I.Click("#Edit_AuthorsButton");
+ string newAuthors = String.Format("These authors are accurate as of {0}.", DateTime.Now.ToString("F"));
+ I.Enter(newAuthors).In("#Edit_Authors");
+
+ I.Click("#Edit_CopyrightButton");
+ string newCopyright = String.Format("Copyright {0}.", DateTime.Now.ToString("F"));
+ I.Enter(newCopyright).In("#Edit_Copyright");
+
+ I.Click("#Edit_TagsButton");
+ string newTags = String.Format("These tags are accurate as of {0}.", DateTime.Now.ToString("F"));
+ I.Enter(newTags).In("#Edit_Tags");
+
+ I.Click("#Edit_ReleaseNotesButton");
+ string newReleaseNotes = String.Format("These release notes are accurate as of {0}.", DateTime.Now.ToString("F"));
+ I.Enter(newReleaseNotes).In("#Edit_ReleaseNotes");
+
+ I.Click("input[value='Submit']");
+
+ // Validate that the edit is queued.
+ I.Expect.Url(UrlHelper.BaseUrl + @"packages/" + packageName + "/" + version);
+ string expectedDescription = @"p:contains('" + newDescription + "')";
+ string unexpectedSummary = @"contains('" + newSummary + "')";
+ string unexpectedIconUrl = "img[src='" + newIconUrl + "']";
+ string expectedIconUrl = "img[src='/Content/Images/packageDefaultIcon.png']";
+ string expectedHomePageUrl = "a[href='" + newHomePageUrl + "']";
+ string unexpectedCopyright = @"contains('" + newCopyright + "')";
+ string expectedReleaseNotes = @"p:contains('" + newReleaseNotes + "')";
+ string editPending = @"p:contains('An edit is pending for this package version.')";
+
+ I.Expect.Count(1).Of(expectedDescription);
+ I.Expect.Count(0).Of(unexpectedSummary); // Summary is not present on the package page.
+ I.Expect.Count(0).Of(unexpectedIconUrl);
+ I.Expect.Count(1).Of(expectedIconUrl);
+ I.Expect.Count(1).Of(expectedHomePageUrl);
+ I.Expect.Text(newAuthors).In("p[class=authors]");
+ I.Expect.Count(0).Of(unexpectedCopyright); // Copyright is not present on the package page.
+ I.Expect.Count(1).Of(expectedReleaseNotes);
+ string[] tags = newTags.Split(" ,;".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
+ foreach (string tag in tags)
+ {
+ I.Expect.Text(tag).In("a[title='Search for " + tag + "']");
+ }
+
+ // Validate the pending edit message.
+ I.Expect.Count(1).Of(editPending);
+
+ // Re-load and validate that the edit has been applied.
+ // The edit can be applied anytime within 5 mins. to be considered successful. This tries 10 times with a 30 sec. timeout.
+ bool applied = false;
+ for (int i = 0; i < 10; i++)
+ {
+ I.Open(UrlHelper.BaseUrl + @"Packages/" + packageName + "/" + version);
+ I.Expect.Count(1).Of(expectedDescription);
+ try
+ {
+ I.Expect.Count(0).Of(editPending);
+ applied = true;
+ }
+ catch
+ {
+ // We expect an exception if the edit hasn't been applied yet.
+ }
+ }
+ Assert.IsTrue(applied, "The edit doesn't appear to have been applied after five minutes.");
+ }
+
+ }
+}
View
119 tests/NuGetGallery.FunctionalTests.Fluent/EditPackageTest.cs
@@ -0,0 +1,119 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Net;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+using NuGetGallery.FunctionTests.Helpers;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using FluentAutomation;
+
+namespace NuGetGallery.FunctionalTests.Fluent
+{
+
+ [TestClass]
+ public class EditPackageTest : NuGetFluentTest
+ {
+ public EditPackageTest()
+ {
+ FluentAutomation.SeleniumWebDriver.Bootstrap();
+ }
+
+ [TestMethod]
+ [Description("Edit every possible metadata field of an uploaded package.")]
+ public void EditPackage()
+ {
+ string packageName = "NuGetGallery.FunctionalTests.Fluent.EditPackageTest";
+ string version = "1.0.0";
+
+ UploadPackageIfNecessary(packageName, version);
+
+ // Log on using the test account.
+ I.LogOn(EnvironmentSettings.TestAccountName, EnvironmentSettings.TestAccountPassword);
+
+ // Navigate to the package's edit page.
+ I.Open(String.Format(UrlHelper.EditPageUrl, packageName, version));
+ I.Expect.Url(x => x.AbsoluteUri.Contains("nuget"));
+
+ // Edit the package.
+ string newTitle = String.Format("This title is accurate as of {0}.", DateTime.Now.ToString("F"));
+ I.Enter(newTitle).In("#Edit_VersionTitle");
+
+ string newDescription = String.Format("This description is accurate as of {0}.", DateTime.Now.ToString("F"));
+ I.Enter(newDescription).In("#Edit_Description");
+
+ string newSummary = String.Format("This summary is accurate as of {0}.", DateTime.Now.ToString("F"));
+ I.Enter(newSummary).In("#Edit_Summary");
+
+ string newIconUrl = String.Format("http://microsoft.com/IconUrl/{0}", DateTime.Now.ToString("FFFFFFF"));
+ I.Enter(newIconUrl).In("#Edit_IconUrl");
+
+ string newHomePageUrl = String.Format("http://microsoft.com/HomePageUrl/{0}", DateTime.Now.ToString("FFFFFFF"));
+ I.Enter(newHomePageUrl).In("#Edit_ProjectUrl");
+
+ string newAuthors = String.Format("These authors are accurate as of {0}.", DateTime.Now.ToString("F"));
+ I.Enter(newAuthors).In("#Edit_Authors");
+
+ string newCopyright = String.Format("Copyright {0}.", DateTime.Now.ToString("F"));
+ I.Enter(newCopyright).In("#Edit_Copyright");
+
+ string newTags = String.Format("These tags are accurate as of {0}.", DateTime.Now.ToString("F"));
+ I.Enter(newTags).In("#Edit_Tags");
+
+ string newReleaseNotes = String.Format("These release notes are accurate as of {0}.", DateTime.Now.ToString("F"));
+ I.Enter(newReleaseNotes).In("#Edit_ReleaseNotes");
+
+ I.Click("input[value=Save]");
+
+ // Validate that the edit is queued.
+ I.Expect.Url(UrlHelper.BaseUrl + @"packages/" + packageName + "/" + version);
+ string expectedDescription = @"p:contains('" + newDescription + "')";
+ string unexpectedSummary = @"contains('" + newSummary + "')";
+ string unexpectedIconUrl = "img[src='" + newIconUrl + "']";
+ string expectedIconUrl = "img[src='/Content/Images/packageDefaultIcon.png']";
+ string expectedHomePageUrl = "a[href='" + newHomePageUrl + "']";
+ string unexpectedCopyright = @"contains('" + newCopyright + "')";
+ string expectedReleaseNotes = @"p:contains('" + newReleaseNotes + "')";
+ string editPending = @"p:contains('An edit is pending for this package version.')";
+
+ I.Expect.Count(1).Of(expectedDescription);
+ I.Expect.Count(0).Of(unexpectedSummary); // Summary is not present on the package page.
+ I.Expect.Count(0).Of(unexpectedIconUrl);
+ I.Expect.Count(1).Of(expectedIconUrl);
+ I.Expect.Count(1).Of(expectedHomePageUrl);
+ I.Expect.Text(newAuthors).In("p[class=authors]");
+ I.Expect.Count(0).Of(unexpectedCopyright); // Copyright is not present on the package page.
+ I.Expect.Count(1).Of(expectedReleaseNotes);
+ string[] tags = newTags.Split(" ,;".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
+ foreach (string tag in tags)
+ {
+ I.Expect.Text(tag).In("a[title='Search for " + tag + "']");
+ }
+
+ // Validate the pending edit message.
+ I.Expect.Count(1).Of(editPending);
+
+ // Re-load and validate that the edit has been applied.
+ // The edit can be applied anytime within 5 mins. to be considered successful. This tries 10 times with a 30 sec. timeout.
+ bool applied = false;
+ for (int i = 0; i < 10; i++)
+ {
+ I.Open(UrlHelper.BaseUrl + @"Packages/" + packageName + "/" + version);
+ I.Expect.Count(1).Of(expectedDescription);
+ try
+ {
+ I.Expect.Count(0).Of(editPending);
+ applied = true;
+ }
+ catch
+ {
+ // We expect an exception if the edit hasn't been applied yet.
+ }
+ }
+ Assert.IsTrue(applied, "The edit doesn't appear to have been applied after five minutes.");
+ }
+
+ }
+}
View
49 tests/NuGetGallery.FunctionalTests.Fluent/ExtensionMethods.cs
@@ -0,0 +1,49 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Net;
+using NuGetGallery.FunctionTests.Helpers;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using FluentAutomation;
+using FluentAutomation.Interfaces;
+
+namespace NuGetGallery.FunctionalTests.Fluent
+{
+ public static class ExtensionMethods
+ {
+
+ public static void LogOn(this INativeActionSyntaxProvider I, string userName, string password)
+ {
+ I.Open(UrlHelper.BaseUrl + "users/account/LogOn");
+ I.Expect.Url(x => x.LocalPath.Contains("LogOn"));
+ I.Enter(EnvironmentSettings.TestAccountName).In("#SignIn_UserNameOrEmail");
+ I.Enter(EnvironmentSettings.TestAccountPassword).In("#SignIn_Password");
+ I.Click("#signin-link");
+ }
+
+ public static void UploadPackageUsingUI(this INativeActionSyntaxProvider I, string fullPackagePath)
+ {
+ // Navigate to the Upload Package page. This will fail if the user never uploaded the previous package, hence the error handling.
+ I.Open(String.Format(UrlHelper.UploadPageUrl));
+ try
+ {
+ I.Expect.Url(x => x.AbsoluteUri.Contains("/packages/Upload"));
+ }
+ catch
+ {
+ I.Click("a[class='cancel']");
+ }
+
+ // Upload the package.
+ I.Click("input[name='UploadFile']");
+ I.Wait(5);
+ I.Type(fullPackagePath);
+ I.Press("{ENTER}");
+ I.Wait(5);
+ I.Click("input[value='Upload']");
+ }
+
+ }
+}
View
62 tests/NuGetGallery.FunctionalTests.Fluent/LogonTest.cs
@@ -0,0 +1,62 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Net;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+using NuGetGallery.FunctionTests.Helpers;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using FluentAutomation;
+
+namespace NuGetGallery.FunctionalTests.Fluent
+{
+
+ [TestClass]
+ public class LogonTest : NuGetFluentTest
+ {
+ public LogonTest()
+ {
+ FluentAutomation.SeleniumWebDriver.Bootstrap();
+ }
+
+ [TestMethod]
+ public void Logon()
+ {
+ LogonHelper("/");
+ LogonHelper("/packages");
+ LogonHelper("/stats");
+ LogonHelper("/policies/Contact");
+ LogonHelper("/policies/Terms");
+ LogonHelper("/policies/Privacy");
+ }
+
+ private void LogonHelper(string page)
+ {
+ I.Open(UrlHelper.BaseUrl + page);
+ I.Expect.Url(x => x.AbsoluteUri.Contains(page));
+
+ string registerSignIn = "a:contains('Register / Sign in')";
+ string signOut = "a:contains('Sign out')";
+ string expectedUserName = "a:contains('NugetTestAccount')";
+
+ I.Click(registerSignIn);
+ I.Expect.Url(x => x.LocalPath.Contains("LogOn"));
+ I.Enter(EnvironmentSettings.TestAccountName).In("#SignIn_UserNameOrEmail");
+ I.Enter(EnvironmentSettings.TestAccountPassword).In("#SignIn_Password");
+ I.Click("#signin-link");
+
+ I.Expect.Url(x => x.AbsoluteUri.Contains(page));
+ I.Expect.Count(0).Of(registerSignIn);
+ I.Expect.Count(1).Of(signOut);
+ I.Expect.Count(1).Of(expectedUserName);
+ I.Click(signOut);
+
+ I.Expect.Url(x => x.AbsoluteUri.Contains(page));
+ I.Expect.Count(1).Of(registerSignIn);
+ I.Expect.Count(0).Of(signOut);
+ I.Expect.Count(0).Of(expectedUserName);
+ }
+ }
+}
View
50 tests/NuGetGallery.FunctionalTests.Fluent/MinClientVersionFromUITest.cs
@@ -0,0 +1,50 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Net;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+using NuGetGallery.FunctionTests.Helpers;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using FluentAutomation;
+
+namespace NuGetGallery.FunctionalTests.Fluent
+{
+
+ [TestClass]
+ public class MinClientVersionFromUITest : NuGetFluentTest
+ {
+ public MinClientVersionFromUITest()
+ {
+ FluentAutomation.SeleniumWebDriver.Bootstrap();
+ }
+
+ [TestMethod]
+ [Description("Upload a package with a MinClientVersion and validate the min client version number in the package page.")]
+ public void MinClientVersionFromUI()
+ {
+ // Use the same package name, but force the version to be unique.
+ string packageName = "NuGetGallery.FunctionalTests.Fluent.MinClientVersionFromUITest";
+ string ticks = DateTime.Now.Ticks.ToString();
+ string version = new System.Version(ticks.Substring(0, 6) + "." + ticks.Substring(6, 6) + "." + ticks.Substring(12, 6)).ToString();
+ string newPackageLocation = PackageCreationHelper.CreatePackage(packageName, version, "2.7");
+
+ // Log on using the test account.
+ I.LogOn(EnvironmentSettings.TestAccountName, EnvironmentSettings.TestAccountPassword);
+
+ // Navigate to the upload page.
+ I.UploadPackageUsingUI(newPackageLocation);
+
+ // Submit on the validate upload page.
+ I.Click("input[value='Submit']");
+
+ // Validate that the minclientversion is shown to the user on the package page.
+ I.Expect.Url(UrlHelper.BaseUrl + @"packages/" + packageName + "/" + version);
+ string expectedMinClientVersion = @"p:contains('Requires NuGet 2.7 or higher')";
+
+ I.Expect.Count(1).Of(expectedMinClientVersion);
+ }
+ }
+}
View
47 tests/NuGetGallery.FunctionalTests.Fluent/NuGetFluentTest.cs
@@ -0,0 +1,47 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Net;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+using NuGetGallery.FunctionTests.Helpers;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using FluentAutomation;
+
+namespace NuGetGallery.FunctionalTests.Fluent
+{
+ public class NuGetFluentTest : FluentTest
+ {
+ public NuGetFluentTest()
+ {
+ FluentAutomation.SeleniumWebDriver.Bootstrap();
+ }
+
+ public void UploadPackageIfNecessary(string packageName, string version)
+ {
+ if (!PackageExists(packageName, version))
+ {
+ AssertAndValidationHelper.UploadNewPackageAndVerify(packageName, version);
+ }
+ }
+
+ public bool PackageExists(string packageName, string version)
+ {
+ HttpWebRequest packagePageRequest = (HttpWebRequest)HttpWebRequest.Create(UrlHelper.BaseUrl + @"Packages/" + packageName + "/" + version);
+ HttpWebResponse packagePageResponse;
+ try
+ {
+ packagePageResponse = (HttpWebResponse)packagePageRequest.GetResponse();
+ }
+ catch (WebException e)
+ {
+ if (((HttpWebResponse)e.Response).StatusCode == HttpStatusCode.NotFound) return false;
+ }
+
+ // If we didn't get an exception, that means thew resource exists.
+ return true;
+ }
+ }
+}
View
104 tests/NuGetGallery.FunctionalTests.Fluent/NuGetGallery.FunctionalTests.Fluent.csproj
@@ -0,0 +1,104 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProjectGuid>{F00643FE-1DA1-4639-9D3E-80D33A91F1C6}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>NuGetGallery.FunctionalTests.Fluent</RootNamespace>
+ <AssemblyName>NuGetGallery.FunctionalTests.Fluent</AssemblyName>
+ <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
+ <FileAlignment>512</FileAlignment>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup>
+ <StartupObject />
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="FluentAutomation.Core">
+ <HintPath>..\..\packages\FluentAutomation.Core.2.2.0.1\lib\net40\FluentAutomation.Core.dll</HintPath>
+ </Reference>
+ <Reference Include="FluentAutomation.SeleniumWebDriver">
+ <HintPath>..\..\packages\FluentAutomation.SeleniumWebDriver.2.2.0.1\lib\net40\FluentAutomation.SeleniumWebDriver.dll</HintPath>
+ </Reference>
+ <Reference Include="Microsoft.VisualStudio.QualityTools.UnitTestFramework, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
+ <SpecificVersion>False</SpecificVersion>
+ <HintPath>C:\Program Files (x86)\Microsoft Visual Studio 11.0\Common7\IDE\PublicAssemblies\Microsoft.VisualStudio.QualityTools.UnitTestFramework.dll</HintPath>
+ </Reference>
+ <Reference Include="Newtonsoft.Json, Version=4.5.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
+ <HintPath>..\..\packages\Newtonsoft.Json.5.0.8\lib\net45\Newtonsoft.Json.dll</HintPath>
+ </Reference>
+ <Reference Include="System" />
+ <Reference Include="System.Core" />
+ <Reference Include="System.Drawing" />
+ <Reference Include="System.Xml.Linq" />
+ <Reference Include="System.Data.DataSetExtensions" />
+ <Reference Include="Microsoft.CSharp" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Xml" />
+ <Reference Include="WebDriver">
+ <HintPath>..\..\packages\Selenium.WebDriver.2.37.0\lib\net40\WebDriver.dll</HintPath>
+ </Reference>
+ <Reference Include="WebDriver.Support">
+ <HintPath>..\..\packages\Selenium.Support.2.37.0\lib\net40\WebDriver.Support.dll</HintPath>
+ </Reference>
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="ExtensionMethods.cs" />
+ <Compile Include="EditPackageAsPartOfUploadTest.cs" />
+ <Compile Include="EditPackageTest.cs" />
+ <Compile Include="LogonTest.cs" />
+ <Compile Include="MinClientVersionFromUITest.cs" />
+ <Compile Include="NuGetFluentTest.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ <Compile Include="StatisticsPageTest.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="App.config" />
+ <None Include="packages.config" />
+ <None Include="Pages.csv">
+ <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+ </None>
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\NuGetGallery.FunctionalTests.Helpers\NuGetGallery.FunctionalTests.Helpers.csproj">
+ <Project>{8fb56455-c688-44ae-95f1-48ffcb199bfe}</Project>
+ <Name>NuGetGallery.FunctionalTests.Helpers</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\NuGetGallery.FunctionalTests\NuGetGallery.FunctionalTests.csproj">
+ <Project>{0a6b1a52-4d26-4946-9ddd-416d01a1adbf}</Project>
+ <Name>NuGetGallery.FunctionalTests</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <ItemGroup>
+ <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+ </ItemGroup>
+ <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project>
View
8 tests/NuGetGallery.FunctionalTests.Fluent/Pages.csv
@@ -0,0 +1,8 @@
+Page
+/
+/packages
+/packages/upload
+/stats
+/policies/Contact
+/policies/Terms
+/policies/Privacy
View
36 tests/NuGetGallery.FunctionalTests.Fluent/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("NuGetGallery.FunctionalTests.Fluent")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("NuGetGallery.FunctionalTests.Fluent")]
+[assembly: AssemblyCopyright("Copyright © 2014")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("15d5a219-f4fb-4c8a-869d-9c56f30c96c3")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
View
56 tests/NuGetGallery.FunctionalTests.Fluent/StatisticsPageTest.cs
@@ -0,0 +1,56 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Net;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+using NuGetGallery.FunctionTests.Helpers;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using FluentAutomation;
+
+namespace NuGetGallery.FunctionalTests.Fluent
+{
+
+ [TestClass]
+ public class StatisticsPageTest : NuGetFluentTest
+ {
+ public StatisticsPageTest()
+ {
+ FluentAutomation.SeleniumWebDriver.Bootstrap();
+ }
+
+ [TestMethod]
+ [Description("Cross-check the contents of the Statistics page against the last6weeks API endpoint.")]
+ public void StatisticsPage()
+ {
+ // Request the last 6 weeks endpoint.
+ WebRequest request = WebRequest.Create(UrlHelper.V2FeedRootUrl + @"stats/downloads/last6weeks/");
+ // Get the response.
+ WebResponse response = request.GetResponse();
+ StreamReader sr = new StreamReader(response.GetResponseStream());
+ string responseText = sr.ReadToEnd();
+
+ // Grab the top 10 package ids in the feed.
+ string[] packageName = new string[10];
+ responseText = packageName[0] = responseText.Substring(responseText.IndexOf(@"""PackageId"": """) + 14);
+ packageName[0] = packageName[0].Substring(0, responseText.IndexOf(@""""));
+ for (int i = 1; i < 10; i++)
+ {
+ responseText = packageName[i] = responseText.Substring(responseText.IndexOf(@"""PackageId"": """) + 14);
+ packageName[i] = packageName[i].Substring(0, responseText.IndexOf(@""""));
+ }
+
+ // Navigate to the stats page.
+ I.Open(UrlHelper.StatsPageUrl);
+ I.Expect.Url(x => x.AbsoluteUri.Contains("stats"));
+
+ for (int i = 0; i < 10; i++)
+ {
+ I.Expect.Exists("td:contains('" + packageName[i] + "')");
+ }
+ I.Expect.Exists("p:contains('Download statistics displayed on this page reflect the actual package downloads from the NuGet.org site.')");
+ }
+ }
+}
View
8 tests/NuGetGallery.FunctionalTests.Fluent/packages.config
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<packages>
+ <package id="FluentAutomation.Core" version="2.2.0.1" targetFramework="net45" />
+ <package id="FluentAutomation.SeleniumWebDriver" version="2.2.0.1" targetFramework="net45" />
+ <package id="Newtonsoft.Json" version="5.0.8" targetFramework="net45" />
+ <package id="Selenium.Support" version="2.37.0" targetFramework="net45" />
+ <package id="Selenium.WebDriver" version="2.37.0" targetFramework="net45" />
+</packages>
View
2  tests/NuGetGallery.FunctionalTests.Helpers/NuspecHelper.cs
@@ -32,7 +32,7 @@ public static string CreateDefaultNuspecFile(string packageName, string version
string filePath = Path.Combine(packageDir, packageName + ".nuspec");
RemoveSampleNuspecValues(filePath);
UpdateNuspecFile(filePath, "1.0.0", version);
-
+ UpdateNuspecFile(filePath, "Package description", "This is a test package created by the NuGet team.");
// Apply the minClientVersion to the spec only if it's defined.
if (minClientVersion != null)
{
View
53 tests/NuGetGallery.FunctionalTests.vsmdi
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<TestLists xmlns="http://microsoft.com/schemas/VisualStudio/TeamTest/2010">
+ <TestList name="SQLDownTests" id="00057c7c-0505-4fd7-83d1-f4dd6a4af0b8" parentListId="8c43106b-9dc1-4907-a29f-aa66a61bf5b6" />
+ <TestList name="P0Tests" id="01372d05-1ac1-4f00-ac37-5ca977686e4e" parentListId="8c43106b-9dc1-4907-a29f-aa66a61bf5b6">
+ <TestLinks>
+ <TestLink id="d527504e-456c-ed4a-8eba-7c20c18ba47d" name="HomePageValidationTest" storage="nugetgallery.functionaltests\bin\nugetgallery.functionaltests.dll" type="Microsoft.VisualStudio.TestTools.WebStress.CodedWebTestElement, Microsoft.VisualStudio.QualityTools.LoadTest, PublicKeyToken=b03f5f7f11d50a3a" />
+ <TestLink id="a1c602d9-292b-1042-380c-707cec091de9" name="LogonTest" storage="nugetgallery.functionaltests\bin\nugetgallery.functionaltests.dll" type="Microsoft.VisualStudio.TestTools.WebStress.CodedWebTestElement, Microsoft.VisualStudio.QualityTools.LoadTest, PublicKeyToken=b03f5f7f11d50a3a" />
+ <TestLink id="80baf145-2a87-1c50-450f-57e4de9d3b4f" name="UploadPackageFromUI" storage="nugetgallery.functionaltests\bin\nugetgallery.functionaltests.dll" type="Microsoft.VisualStudio.TestTools.WebStress.CodedWebTestElement, Microsoft.VisualStudio.QualityTools.LoadTest, PublicKeyToken=b03f5f7f11d50a3a" />
+ <TestLink id="cc44bdbd-ce3e-69f6-f020-1fcb65293738" name="DownloadPackageFromV2Feed" storage="nugetgallery.functionaltests\bin\nugetgallery.functionaltests.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, Version=11.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
+ <TestLink id="916d542f-9953-383f-a9cc-e87980667cf3" name="RestorePackageFromV2Feed" storage="nugetgallery.functionaltests\bin\nugetgallery.functionaltests.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, Version=11.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
+ </TestLinks>
+ </TestList>
+ <TestList name="Lists of Tests" id="8c43106b-9dc1-4907-a29f-aa66a61bf5b6">
+ <RunConfiguration id="62f583f0-2eca-4773-bed0-474a13faad76" name="Local" storage="local.testsettings" type="Microsoft.VisualStudio.TestTools.Common.TestRunConfiguration, Microsoft.VisualStudio.QualityTools.Common, Version=11.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
+ </TestList>
+ <TestList name="AllHappyPathTests" id="b836686b-8922-4ce2-8bcc-bd368809954a" parentListId="8c43106b-9dc1-4907-a29f-aa66a61bf5b6">
+ <TestLinks>
+ <TestLink id="a6f81ddd-4476-9109-b107-ff9673898e71" name="ContactOwnerTest" storage="nugetgallery.functionaltests\bin\nugetgallery.functionaltests.dll" type="Microsoft.VisualStudio.TestTools.WebStress.CodedWebTestElement, Microsoft.VisualStudio.QualityTools.LoadTest, PublicKeyToken=b03f5f7f11d50a3a" />
+ <TestLink id="2a6c6363-3869-0c15-2d51-409738bef970" name="FindPackagesByIdTest" storage="nugetgallery.functionaltests\bin\nugetgallery.functionaltests.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, Version=11.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
+ <TestLink id="a1c602d9-292b-1042-380c-707cec091de9" name="LogonTest" storage="nugetgallery.functionaltests\bin\nugetgallery.functionaltests.dll" type="Microsoft.VisualStudio.TestTools.WebStress.CodedWebTestElement, Microsoft.VisualStudio.QualityTools.LoadTest, PublicKeyToken=b03f5f7f11d50a3a" />
+ <TestLink id="916d542f-9953-383f-a9cc-e87980667cf3" name="RestorePackageFromV2Feed" storage="nugetgallery.functionaltests\bin\nugetgallery.functionaltests.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, Version=11.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
+ <TestLink id="baeffb56-e5a3-71a3-dcf4-ca714ba14856" name="UploadPackageWithNuGetCommandLineTest" storage="nugetgallery.functionaltests\bin\nugetgallery.functionaltests.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, Version=11.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
+ <TestLink id="f206f30d-af4b-ae66-9032-732bc03336c1" name="DownPackageWithNuGetCommandLineTest" storage="nugetgallery.functionaltests\bin\nugetgallery.functionaltests.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, Version=11.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
+ <TestLink id="5ceca307-8fd2-e863-65bb-d8151e5dafba" name="PackagesPageTest" storage="nugetgallery.functionaltests\bin\nugetgallery.functionaltests.dll" type="Microsoft.VisualStudio.TestTools.WebStress.CodedWebTestElement, Microsoft.VisualStudio.QualityTools.LoadTest, PublicKeyToken=b03f5f7f11d50a3a" />
+ <TestLink id="d527504e-456c-ed4a-8eba-7c20c18ba47d" name="HomePageValidationTest" storage="nugetgallery.functionaltests\bin\nugetgallery.functionaltests.dll" type="Microsoft.VisualStudio.TestTools.WebStress.CodedWebTestElement, Microsoft.VisualStudio.QualityTools.LoadTest, PublicKeyToken=b03f5f7f11d50a3a" />
+ <TestLink id="80baf145-2a87-1c50-450f-57e4de9d3b4f" name="UploadPackageFromUI" storage="nugetgallery.functionaltests\bin\nugetgallery.functionaltests.dll" type="Microsoft.VisualStudio.TestTools.WebStress.CodedWebTestElement, Microsoft.VisualStudio.QualityTools.LoadTest, PublicKeyToken=b03f5f7f11d50a3a" />
+ <TestLink id="cc44bdbd-ce3e-69f6-f020-1fcb65293738" name="DownloadPackageFromV2Feed" storage="nugetgallery.functionaltests\bin\nugetgallery.functionaltests.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, Version=11.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
+ <TestLink id="02d43bf4-c2fb-43fb-6999-a16887a86fa6" name="GetUpdatesTest" storage="nugetgallery.functionaltests\bin\nugetgallery.functionaltests.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, Version=11.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
+ <TestLink id="5d62a4b0-dcba-4028-434b-2b747b4c411f" name="UploadMultipleVersionOfPackage" storage="nugetgallery.functionaltests\bin\nugetgallery.functionaltests.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, Version=11.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
+ <TestLink id="42a9bfc6-ed87-df50-c848-82aca2c8fd0d" name="ManagePackagesPageTest" storage="nugetgallery.functionaltests\bin\nugetgallery.functionaltests.dll" type="Microsoft.VisualStudio.TestTools.WebStress.CodedWebTestElement, Microsoft.VisualStudio.QualityTools.LoadTest, PublicKeyToken=b03f5f7f11d50a3a" />
+ <TestLink id="0449da0f-5881-ffca-f9d0-f7c0ad709071" name="UploadPackageWithoutLoginTest" storage="nugetgallery.functionaltests\bin\nugetgallery.functionaltests.dll" type="Microsoft.VisualStudio.TestTools.WebStress.CodedWebTestElement, Microsoft.VisualStudio.QualityTools.LoadTest, PublicKeyToken=b03f5f7f11d50a3a" />
+ <TestLink id="428c8a13-f822-cffc-6ae0-78452d15e1fb" name="RegisterNewUserTest" storage="nugetgallery.functionaltests\bin\nugetgallery.functionaltests.dll" type="Microsoft.VisualStudio.TestTools.WebStress.CodedWebTestElement, Microsoft.VisualStudio.QualityTools.LoadTest, PublicKeyToken=b03f5f7f11d50a3a" />
+ <TestLink id="04cd200b-33df-3564-ded5-686cdfe44f77" name="DownloadPackageWithNuGetCoreTest" storage="nugetgallery.functionaltests\bin\nugetgallery.functionaltests.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, Version=11.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
+ <TestLink id="596ceb57-0d0f-7e7b-bed1-471bcdf59526" name="DownloadStatsForNewlyUploadedPackage" storage="nugetgallery.functionaltests\bin\nugetgallery.functionaltests.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, Version=11.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
+ <TestLink id="9387a1a2-3523-2e44-8030-533d344923cf" name="DeletePackageTest" storage="nugetgallery.functionaltests\bin\nugetgallery.functionaltests.dll" type="Microsoft.VisualStudio.TestTools.WebStress.CodedWebTestElement, Microsoft.VisualStudio.QualityTools.LoadTest, PublicKeyToken=b03f5f7f11d50a3a" />
+ </TestLinks>
+ </TestList>
+ <TestList name="ReadOnlyModeTests" id="f9b8ac1f-7978-4738-afc2-6918b063e5c3" parentListId="8c43106b-9dc1-4907-a29f-aa66a61bf5b6">
+ <TestLinks>
+ <TestLink id="04cd200b-33df-3564-ded5-686cdfe44f77" name="DownloadPackageWithNuGetCoreTest" storage="nugetgallery.functionaltests\bin\nugetgallery.functionaltests.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, Version=11.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
+ <TestLink id="9ad6e2e2-a082-8088-00f6-e05079fd89a0" name="StatisticsPageTest" storage="nugetgallery.functionaltests\bin\nugetgallery.functionaltests.dll" type="Microsoft.VisualStudio.TestTools.WebStress.CodedWebTestElement, Microsoft.VisualStudio.QualityTools.LoadTest, PublicKeyToken=b03f5f7f11d50a3a" />
+ <TestLink id="f206f30d-af4b-ae66-9032-732bc03336c1" name="DownPackageWithNuGetCommandLineTest" storage="nugetgallery.functionaltests\bin\nugetgallery.functionaltests.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, Version=11.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
+ <TestLink id="a1c602d9-292b-1042-380c-707cec091de9" name="LogonTest" storage="nugetgallery.functionaltests\bin\nugetgallery.functionaltests.dll" type="Microsoft.VisualStudio.TestTools.WebStress.CodedWebTestElement, Microsoft.VisualStudio.QualityTools.LoadTest, PublicKeyToken=b03f5f7f11d50a3a" />
+ <TestLink id="d527504e-456c-ed4a-8eba-7c20c18ba47d" name="HomePageValidationTest" storage="nugetgallery.functionaltests\bin\nugetgallery.functionaltests.dll" type="Microsoft.VisualStudio.TestTools.WebStress.CodedWebTestElement, Microsoft.VisualStudio.QualityTools.LoadTest, PublicKeyToken=b03f5f7f11d50a3a" />
+ <TestLink id="c320789f-a801-c187-e7d8-0f17b24ff835" name="ReadOnlyModeRegisterNewUserTest" storage="nugetgallery.functionaltests\bin\nugetgallery.functionaltests.dll" type="Microsoft.VisualStudio.TestTools.WebStress.CodedWebTestElement, Microsoft.VisualStudio.QualityTools.LoadTest, PublicKeyToken=b03f5f7f11d50a3a" />
+ </TestLinks>
+ </TestList>
+ <TestList name="FluentTests" id="01372d05-1ac1-4f00-ac37-5ca977686e4f" parentListId="8c43106b-9dc1-4907-a29f-aa66a61bf5b6">
+ <TestLinks>
+ <TestLink id="d527504e-456c-ed4a-8eba-7c20c18ba47f" name="EditPackageTest" storage="NuGetGallery.FunctionalTests.Fluent\bin\Debug\nugetgallery.functionaltests.fluent.dll" type="Microsoft.VisualStudio.TestTools.WebStress.CodedWebTestElement, Microsoft.VisualStudio.QualityTools.LoadTest, PublicKeyToken=b03f5f7f11d50a3a" />
+ </TestLinks>
+ </TestList>
+</TestLists>
View
93 tests/NuGetGallery.FunctionalTests/Features/CuratedFeedTest.cs
@@ -27,34 +27,28 @@ public TestContext TestContext
}
[TestMethod]
- [Description("Creates a package with Windows8 tags. Uploads it and checks if it has been curated")]
- [Priority(1)]
- [Ignore]
- public void AddPackageToWindows8CuratedFeed()
- {
- string packageId = testContextInstance.TestName + DateTime.Now.Ticks.ToString();
- string packageFullPath = PackageCreationHelper.CreateWindows8CuratedPackage(packageId);
- int exitCode = CmdLineHelper.UploadPackage(packageFullPath, UrlHelper.V2FeedPushSourceUrl);
- Assert.IsTrue((exitCode == 0), "The package upload via Nuget.exe didnt suceed properly. Check the logs to see the process error and output stream");
- //check if the package is present in windows 8 feed.
- //TBD : Need to check the exact the url for curated feed.
- System.Threading.Thread.Sleep(60000);
- Assert.IsTrue(ClientSDKHelper.CheckIfPackageExistsInSource(packageId, UrlHelper.Windows8CuratedFeedUrl), "Package {0} is not found in the site {1} after uploading.", packageId, UrlHelper.Windows8CuratedFeedUrl);
- }
-
- [TestMethod]
[Description("Performs a querystring-based search of the Windows 8 curated feed. Confirms expected packages are returned.")]
public void SearchWindows8CuratedFeed()
{
- WebRequest request = WebRequest.Create(UrlHelper.V2FeedRootUrl + @"curated-feeds/Windows8-Packages/Search()?$filter=IsLatestVersion&$skip=0&$top=10&searchTerm='Unity'&includePrerelease=false");
- // Get the response.
- WebResponse response = request.GetResponse();
- StreamReader sr = new StreamReader(response.GetResponseStream());
- string responseText = sr.ReadToEnd();
+ string packageName = "NuGetGallery.FunctionalTests.SearchWindows8CuratedFeed";
+ string ticks = DateTime.Now.Ticks.ToString();
+ string version = new System.Version(ticks.Substring(0, 6) + "." + ticks.Substring(6, 6) + "." + ticks.Substring(12, 6)).ToString();
+ string packageFullPath = PackageCreationHelper.CreateWindows8CuratedPackage(packageName, version);
+
+ int exitCode = CmdLineHelper.UploadPackage(packageFullPath, UrlHelper.V2FeedPushSourceUrl);
+ Assert.IsTrue((exitCode == 0), "The package upload via Nuget.exe didnt suceed properly. Check the logs to see the process error and output stream");
- Assert.IsTrue(responseText.Contains(@"<title type=""text"">Unity</title>"), "The expected package title wasn't found in the feed. Feed contents: " + responseText);
- Assert.IsTrue(responseText.Contains(@"<content type=""application/zip"" src=""" + UrlHelper.V2FeedRootUrl + "curated-feeds/package/Unity/"), "The expected package URL wasn't found in the feed. Feed contents: " + responseText);
- Assert.IsFalse(responseText.Contains(@"jquery"), "The feed contains non-matching package names. Feed contents: " + responseText);
+ // The feed could update anytime in the next 5 minutes and this test would be considered a success.
+ bool applied = false;
+ for (int i = 0; i < 10 && applied == false; i++)
+ {
+ System.Threading.Thread.Sleep(30000);
+ if (ClientSDKHelper.CheckIfPackageExistsInSource(packageName, UrlHelper.Windows8CuratedFeedUrl))
+ {
+ applied = true;
+ }
+ }
+ Assert.IsTrue(applied, "Package {0} is not found in the site {1} after uploading.", packageName, UrlHelper.Windows8CuratedFeedUrl);
}
@@ -62,16 +56,57 @@ public void SearchWindows8CuratedFeed()
[Description("Performs a querystring-based search of the WebMatrix curated feed. Confirms expected packages are returned.")]
public void SearchWebMatrixCuratedFeed()
{
- WebRequest request = WebRequest.Create(UrlHelper.V2FeedRootUrl + @"curated-feeds/webmatrix/Search()?$filter=IsLatestVersion&$skip=0&$top=10&searchTerm='asp.net%20web%20helpers'&targetFramework='net40'&includePrerelease=false");
+ string packageName = "NuGetGallery.FunctionalTests.SearchWebMatrixCuratedFeed";
+ string ticks = DateTime.Now.Ticks.ToString();
+ string version = new System.Version(ticks.Substring(0, 6) + "." + ticks.Substring(6, 6) + "." + ticks.Substring(12, 6)).ToString();
+ string packageFullPath = PackageCreationHelper.CreateWebMatrixCuratedPackage(packageName, version);
+
+ int exitCode = CmdLineHelper.UploadPackage(packageFullPath, UrlHelper.V2FeedPushSourceUrl);
+ Assert.IsTrue((exitCode == 0), "The package upload via Nuget.exe didnt suceed properly. Check the logs to see the process error and output stream");
+
+ // The feed could update anytime in the next 5 minutes and this test would be considered a success.
+ bool applied = false;
+ for (int i = 0; i < 10 && applied == false; i++)
+ {
+ System.Threading.Thread.Sleep(30000);
+ if (ClientSDKHelper.CheckIfPackageExistsInSource(packageName, UrlHelper.WebMatrixCuratedFeedUrl))
+ {
+ applied = true;
+ }
+ }
+ Assert.IsTrue(applied, "Package {0} is not found in the site {1} after uploading.", packageName, UrlHelper.WebMatrixCuratedFeedUrl);
+ }
+
+ [TestMethod]
+ [Description("Validates the microsoftdotnet feed, including the next page link")]
+ public void ValidateMicrosoftDotNetCuratedFeed()
+ {
+ WebRequest request = WebRequest.Create(UrlHelper.V2FeedRootUrl + @"/curated-feeds/microsoftdotnet/Packages");
+
// Get the response.
WebResponse response = request.GetResponse();
StreamReader sr = new StreamReader(response.GetResponseStream());
string responseText = sr.ReadToEnd();
+
+ // Make sure that 40 entries are returned. This means that if we split on the <entry> tag, we'd have 41 strings.
+ int length = responseText.Split(new string[] { "<entry>" }, StringSplitOptions.RemoveEmptyEntries).Length;
+ Assert.IsTrue(length == 41, "An unexpected number of entries was found. Actual number was " + (length - 1));
+
+ // Get the link to the next page.
+ string link = responseText.Split(new string [] { @"<link rel=""next"" href=""" }, StringSplitOptions.RemoveEmptyEntries)[1];
+ link = link.Substring(0, link.IndexOf(@""""));
- Assert.IsTrue(responseText.Contains(@"<title type=""text"">microsoft-web-helpers</title>"), "The expected package title wasn't found in the feed. Feed contents: " + responseText);
- Assert.IsTrue(responseText.Contains(@"<content type=""application/zip"" src=""" + UrlHelper.V2FeedRootUrl + "curated-feeds/package/microsoft-web-helpers/"), "The expected package URL wasn't found in the feed. Feed contents: " + responseText);
- Assert.IsFalse(responseText.Contains(@"jquery"), "The feed contains non-matching package names. Feed contents: " + responseText);
-
+ request = WebRequest.Create(UrlHelper.V2FeedRootUrl + @"/curated-feeds/microsoftdotnet/Packages");
+
+ // Get the response.
+ try
+ {
+ response = (HttpWebResponse)request.GetResponse();
+ }
+ catch (WebException e)
+ {
+ if (((HttpWebResponse)e.Response).StatusCode != HttpStatusCode.OK) Assert.Fail("Next page link is broken. Expected 200, got " + ((HttpWebResponse)e.Response).StatusCode);
+ }
}
}
}
View
23 tests/NuGetGallery.FunctionalTests/ODataTests/V2FeedExtendedTest.cs
@@ -39,6 +39,29 @@ public void FindPackagesByIdTest()
}
+
+ [TestMethod]
+ public void GetUpdatesTest()
+ {
+ // Use the same package name, but force the version to be unique.
+ string packageName = "NuGetGallery.FunctionalTests.Fluent.GetUpdatesTest";
+ string ticks = DateTime.Now.Ticks.ToString();
+ string version1 = new System.Version(ticks.Substring(0, 6) + "." + ticks.Substring(6, 6) + "." + ticks.Substring(12, 6)).ToString();
+ string version2 = new System.Version(Convert.ToInt32((ticks.Substring(0, 6)) + 1).ToString() + "." + ticks.Substring(6, 6) + "." + ticks.Substring(12, 6)).ToString();
+ AssertAndValidationHelper.UploadNewPackageAndVerify(packageName, version1);
+ AssertAndValidationHelper.UploadNewPackageAndVerify(packageName, version2);
+
+ WebRequest request = WebRequest.Create(UrlHelper.V2FeedRootUrl + @"/GetUpdates()?packageIds='NuGetGallery.FunctionalTests.Fluent.GetUpdatesTest%7COwin%7CMicrosoft.Web.Infrastructure%7CMicrosoft.AspNet.Identity.Core%7CMicrosoft.AspNet.Identity.EntityFramework%7CMicrosoft.AspNet.Identity.Owin%7CMicrosoft.AspNet.Web.Optimization%7CRespond%7CWebGrease%7CjQuery%7CjQuery.Validation%7CMicrosoft.Owin.Security.Twitter%7CMicrosoft.Owin.Security.OAuth%7CMicrosoft.Owin.Security.MicrosoftAccount%7CMicrosoft.Owin.Security.Google%7CMicrosoft.Owin.Security.Facebook%7CMicrosoft.Owin.Security.Cookies%7CMicrosoft.Owin%7CMicrosoft.Owin.Host.SystemWeb%7CMicrosoft.Owin.Security%7CModernizr%7CMicrosoft.jQuery.Unobtrusive.Validation%7CMicrosoft.AspNet.WebPages%7CMicrosoft.AspNet.Razor%7Cbootstrap%7CAntlr%7CMicrosoft.AspNet.Mvc%7CNewtonsoft.Json%7CEntityFramework'&versions='" + version1 + "%7C1.0%7C1.0.0.0%7C1.0.0%7C1.0.0%7C1.0.0%7C1.1.1%7C1.2.0%7C1.5.2%7C1.10.2%7C1.11.1%7C2.0.0%7C2.0.0%7C2.0.0%7C2.0.0%7C2.0.0%7C2.0.0%7C2.0.0%7C2.0.0%7C2.0.0%7C2.6.2%7C3.0.0%7C3.0.0%7C3.0.0%7C3.0.0%7C3.4.1.9004%7C5.0.0%7C5.0.6%7C6.0.0'&includePrerelease=false&includeAllVersions=false&targetFrameworks='net45'&versionConstraints='%7C%7C%7C%7C%7C%7C%7C%7C%7C%7C%7C%7C%7C%7C%7C%7C%7C%7C%7C%7C%7C%7C%7C%7C%7C%7C%7C%7C'");
+ // Get the response.
+ WebResponse response = request.GetResponse();
+ StreamReader sr = new StreamReader(response.GetResponseStream());
+ string responseText = sr.ReadToEnd();
+
+ // Verify version 2 is in the output.
+ Assert.IsTrue(responseText.Contains(@"<title type=""text"">NuGetGallery.FunctionalTests.Fluent.GetUpdatesTest</title>"));
+ Assert.IsTrue(responseText.Contains(@"<d:Version>" + version2 + "</d:Version><d:NormalizedVersion>" + version2 + "</d:NormalizedVersion>"));
+ }
+
/// <summary>
/// Double-checks whether feed and stats page rankings are the same.
/// </summary>
View
8 tests/NuGetGallery.FunctionalTests/WebUITests/AccountManagement/InvalidLogonTest.cs
@@ -24,9 +24,9 @@ public override IEnumerator<WebTestRequest> GetRequestEnumerator()
yield return registerPageRequest;
registerPageRequest = null;
- WebTestRequest registerPagePostRequest = new WebTestRequest(UrlHelper.RegisterPageUrl);
+ WebTestRequest registerPagePostRequest = new WebTestRequest(UrlHelper.SignInPageUrl);
registerPagePostRequest.Method = "POST";
- registerPagePostRequest.ExpectedResponseUrl = UrlHelper.RegistrationPendingPageUrl;
+ registerPagePostRequest.ExpectedResponseUrl = UrlHelper.SignInPageUrl;
//create a form and set the UserName, Email and password as form post parameters.
//We just need to set some unique user name and Email.
FormPostHttpBody registerNewUserFormPost = new FormPostHttpBody();
@@ -37,8 +37,8 @@ public override IEnumerator<WebTestRequest> GetRequestEnumerator()
registerNewUserFormPost.FormPostParameters.Add(Constants.PasswordFormField, EnvironmentSettings.TestAccountPassword);
registerPagePostRequest.Body = registerNewUserFormPost;
- //Validate the response to make sure that it has the pending confirmation text in it.
- ValidationRuleFindText PendingConfirmationTextRule = AssertAndValidationHelper.GetValidationRuleForFindText(Constants.RegisterNewUserPendingConfirmationText);
+ //Validate the response to make sure that it doesn't have the pending confirmation text in it.
+ ValidationRuleFindText PendingConfirmationTextRule = AssertAndValidationHelper.GetValidationRuleForFindText(Constants.RegisterNewUserPendingConfirmationText, false);
registerPagePostRequest.ValidateResponse += new EventHandler<ValidationEventArgs>(PendingConfirmationTextRule.Validate);
yield return registerPagePostRequest;
registerPagePostRequest = null;
View
2  tests/NuGetGallery.FunctionalTests/WebUITests/AssertAndValidationHelper.cs
@@ -128,7 +128,7 @@ public static WebTestRequest GetEditPackagePostRequest(WebTest test, string pack
WebTestRequest editPackagePostRequest = new WebTestRequest(String.Format(UrlHelper.EditPageUrl, packageId, version));
editPackagePostRequest.Method = "POST";
editPackagePostRequest.ExpectedResponseUrl = UrlHelper.GetPackagePageUrl(packageId, version);
- Assert.Fail("ExpectedResponseUrl is " + editPackagePostRequest.ExpectedResponseUrl);
+ //Assert.Fail("ExpectedResponseUrl is " + editPackagePostRequest.ExpectedResponseUrl);
FormPostHttpBody logonRequestFormPostBody = new FormPostHttpBody();
logonRequestFormPostBody.FormPostParameters.Add("__RequestVerificationToken", test.Context["$HIDDEN1.__RequestVerificationToken"].ToString());
logonRequestFormPostBody.FormPostParameters.Add("Edit.VersionTitle", title);
View
18 tests/NuGetGallery.FunctionalTests/WebUITests/PackageManagement/EditPackageTest.cs
@@ -72,15 +72,23 @@ public override IEnumerator<WebTestRequest> GetRequestEnumerator()
yield return verifyEditRequest;
verifyEditRequest = null;
- // TO DO: Post isn't weorking and I need to investigate why. I'll investigate more later, but the current verification is still
- // useful in the meantime. [clayco 11/13/2013]
- WebTestRequest verifyEditPostRequest = AssertAndValidationHelper.GetEditPackagePostRequest(this, packageId, "1.0.0", description: "This is a new description.");
+ WebTestRequest verifyEditPostRequest = AssertAndValidationHelper.GetEditPackagePostRequest(this, packageId, "1.0.0", description: "This is a new description.", authors: "clayco", copyright: "Copyright 2014", tags:"Tag1 Tag2", summary:"This is a summary.");
ValidationRuleFindText newDescriptionValidationRule = AssertAndValidationHelper.GetValidationRuleForFindText(@"This is a new description.");
- //ValidationRuleFindText pendingEditValidationRule = AssertAndValidationHelper.GetValidationRuleForFindText(@"An edit is pending for this package version. You are seeing the <em>edited</em> package description now.");
+ ValidationRuleFindText pendingEditValidationRule = AssertAndValidationHelper.GetValidationRuleForFindText(@"An edit is pending for this package version.");
verifyEditPostRequest.ValidateResponse += new EventHandler<ValidationEventArgs>(newDescriptionValidationRule.Validate);
- //verifyEditPostRequest.ValidateResponse += new EventHandler<ValidationEventArgs>(pendingEditValidationRule.Validate);
+ verifyEditPostRequest.ValidateResponse += new EventHandler<ValidationEventArgs>(pendingEditValidationRule.Validate);
yield return verifyEditPostRequest;
verifyEditPostRequest = null;
+
+ // wait a minute.
+ System.Threading.Thread.Sleep(60000);
+ WebTestRequest verifyProcessedRequest = new WebTestRequest(UrlHelper.GetPackagePageUrl(packageId, "1.0.0"));
+ ValidationRuleFindText noPendingEditValidationRule = AssertAndValidationHelper.GetValidationRuleForFindText(@"An edit is pending for this package version.", false);
+ verifyProcessedRequest.ValidateResponse += new EventHandler<ValidationEventArgs>(newDescriptionValidationRule.Validate);
<