From c23efec854ccb486865e00dccb07a6517dadb342 Mon Sep 17 00:00:00 2001 From: Warren Buckley Date: Mon, 7 Jun 2021 12:23:15 +0100 Subject: [PATCH] .NETCore & SQL Docker Image for Container Isolated Development & GitHub CodeSpaces (#9835) * .NETCore & SQL Docker Image https://github.com/microsoft/vscode-dev-containers/tree/master/containers/dotnet-mssql * Set the C# extension aka Omnisharp to use the umbraco-netcore-only.sln * A new script in the postCreate of the docker image to npm install client stuff and initial dotnet build of SLN to help just running straight away * Remove bash script - doing npm install stuff & dotnet build was hard to see log output and taking longer for image to start * Adds in port 9000 and friendly label * Ensure user notified about auto port forward with notification * Comment out image min of assets as causing problems and eating way too much time up atm - need to revisit * Automated launch & tasks VSCode JSON files - updated to run client npm install and npm run build before running website * Update .gitattributes for line ending help for codespaces https://code.visualstudio.com/docs/remote/troubleshooting#_resolving-git-line-ending-issues-in-containers-resulting-in-many-modified-files * Tidy up * Remove npm install from the npm run build step - kinda annoying when you re-run it * Rather everytime attaching the debugger doing a full npm install, gulp dev and dotnet build is overkill, just build the SLN before debugging * Update gitignore with casing rules * Revert "Update .gitattributes for line ending help for codespaces" This reverts commit 28316d1ba8a552751eef2f211b68531484344153. * Sets the global user for npm as root https://stackoverflow.com/a/45505787 * File permission stuff for NPM & Gifsicle binary source compilation from gulp-imagemin * Revert "Comment out image min of assets as causing problems and eating way too much time up atm - need to revisit" This reverts commit be48db9653bc58a69422d131b65955985e115e29. * Add chromium-browser to try & get JS tests to run happy in CodeSpaces * Set DB connection string & unattended install config to true so we can skip installer flow * Add in ENV variables to setup the unattended install user * Try to add SMTP4Dev from Bjarke Recommendation * Need to specify the port mappings for SMTP4Dev * Lovely syntax error in docker compose file * Update ENV variables to renamed settings now this feature merged into NETCore branch by Bjarke * Needed to match the hostname that SMTP4Dev was listening on, had assumed it would be reachable via localhost * Fix folder naminng to make UNIX happy running JS tests Co-authored-by: Bjarke Berg --- .devcontainer/Dockerfile | 45 +++++++ .devcontainer/devcontainer.json | 61 ++++++++++ .devcontainer/docker-compose.yml | 115 ++++++++++++++++++ .devcontainer/library-scripts/azcli-debian.sh | 33 +++++ .devcontainer/mssql/BlankDb.sql | 11 ++ .devcontainer/mssql/installSQLtools.sh | 16 +++ .devcontainer/mssql/postCreateCommand.sh | 64 ++++++++++ .gitignore | 19 +-- .vscode/launch.json | 36 ++++++ .vscode/tasks.json | 67 ++++++++++ .../Routing/ContentFinderByUrlAliasTests.cs | 63 ++++++++++ 11 files changed, 523 insertions(+), 7 deletions(-) create mode 100644 .devcontainer/Dockerfile create mode 100644 .devcontainer/devcontainer.json create mode 100644 .devcontainer/docker-compose.yml create mode 100644 .devcontainer/library-scripts/azcli-debian.sh create mode 100644 .devcontainer/mssql/BlankDb.sql create mode 100644 .devcontainer/mssql/installSQLtools.sh create mode 100644 .devcontainer/mssql/postCreateCommand.sh create mode 100644 .vscode/launch.json create mode 100644 .vscode/tasks.json create mode 100644 src/Umbraco.Tests.UnitTests/Umbraco.Core/Routing/ContentFinderByUrlAliasTests.cs diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile new file mode 100644 index 0000000000..c62ad1c494 --- /dev/null +++ b/.devcontainer/Dockerfile @@ -0,0 +1,45 @@ +# [Choice] .NET Core version: 5.0, 3.1, 2.1 +ARG VARIANT=3.1 +FROM mcr.microsoft.com/vscode/devcontainers/dotnetcore:0-${VARIANT} + +# [Option] Install Node.js +ARG INSTALL_NODE="true" +ARG NODE_VERSION="lts/*" +RUN if [ "${INSTALL_NODE}" = "true" ]; then su vscode -c "umask 0002 && . /usr/local/share/nvm/nvm.sh && nvm install ${NODE_VERSION} 2>&1"; fi + +# [Option] Install Azure CLI +ARG INSTALL_AZURE_CLI="false" +COPY library-scripts/azcli-debian.sh /tmp/library-scripts/ +RUN if [ "$INSTALL_AZURE_CLI" = "true" ]; then bash /tmp/library-scripts/azcli-debian.sh; fi \ + && apt-get clean -y && rm -rf /var/lib/apt/lists/* /tmp/library-scripts + +# Install SQL Tools: SQLPackage and sqlcmd +COPY mssql/installSQLtools.sh installSQLtools.sh +RUN bash ./installSQLtools.sh \ + && apt-get clean -y && rm -rf /var/lib/apt/lists/* /tmp/library-scripts + +# Update args in docker-compose.yaml to set the UID/GID of the "vscode" user. +ARG USER_UID=1000 +ARG USER_GID=$USER_UID +RUN if [ "$USER_GID" != "1000" ] || [ "$USER_UID" != "1000" ]; then groupmod --gid $USER_GID vscode && usermod --uid $USER_UID --gid $USER_GID vscode; fi + + +# [Optional] Uncomment this section to install additional OS packages. +# Following added by Warren... +# Needed to add as Gifsicle used by gulp-imagemin does not ship a Linux binary and has to be compiled from source +# And this Linux package is needed in order to build it +# https://github.com/imagemin/imagemin-gifsicle/issues/40#issuecomment-616487214 +RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \ + && apt-get -y install --no-install-recommends dh-autoreconf chromium-browser + +# [Optional] Uncomment this line to install global node packages. +# RUN su vscode -c "source /usr/local/share/nvm/nvm.sh && npm install -g " 2>&1 + +# Following added by Warren... +# Sets the global user for npm as 'root' due to some permission errors for gulp-imagemin creating binaries +# https://stackoverflow.com/a/45505787 +# +# Needing to set unsafe-perm as root is the user setup +# https://docs.npmjs.com/cli/v6/using-npm/config#unsafe-perm +# Default: false if running as root, true otherwise (we are ROOT) +RUN npm -g config set user vscode && npm -g config set unsafe-perm \ No newline at end of file diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json new file mode 100644 index 0000000000..c1c120d0cf --- /dev/null +++ b/.devcontainer/devcontainer.json @@ -0,0 +1,61 @@ +// For format details, see https://aka.ms/devcontainer.json. For config options, see the README at: +// https://github.com/microsoft/vscode-dev-containers/tree/v0.158.0/containers/dotnet-mssql +{ + "name": "C# (.NET) and MS SQL", + "dockerComposeFile": "docker-compose.yml", + "service": "app", + "workspaceFolder": "/workspace", + + // Set *default* container specific settings.json values on container create. + "settings": { + "terminal.integrated.shell.linux": "/bin/bash", + "mssql.connections": [ + { + "server": "localhost,1433", + "database": "", + "authenticationType": "SqlLogin", + "user": "sa", + "password": "P@ssw0rd", + "emptyPasswordInput": false, + "savePassword": false, + "profileName": "mssql-container" + } + ], + "omnisharp.defaultLaunchSolution": "umbraco-netcore-only.sln", + "omnisharp.enableDecompilationSupport": true, + "omnisharp.enableRoslynAnalyzers": true + }, + + // Add the IDs of extensions you want installed when the container is created. + "extensions": [ + "ms-dotnettools.csharp", + "ms-mssql.mssql" + ], + + // Use 'forwardPorts' to make a list of ports inside the container available locally. + // 1433 for SQL if you want to connect from local into the one running inside the container + // Can connect to the SQL Server running in the image on local with 'host.docker.internal' as hostname + "forwardPorts": [1433, 9000, 5000, 25], + + // [Optional] To reuse of your local HTTPS dev cert: + // + // 1. Export it locally using this command: + // * Windows PowerShell: + // dotnet dev-certs https --trust; dotnet dev-certs https -ep "$env:USERPROFILE/.aspnet/https/aspnetapp.pfx" -p "SecurePwdGoesHere" + // * macOS/Linux terminal: + // dotnet dev-certs https --trust; dotnet dev-certs https -ep "${HOME}/.aspnet/https/aspnetapp.pfx" -p "SecurePwdGoesHere" + // + // 2. Uncomment these 'remoteEnv' lines: + // "remoteEnv": { + // "ASPNETCORE_Kestrel__Certificates__Default__Password": "SecurePwdGoesHere", + // "ASPNETCORE_Kestrel__Certificates__Default__Path": "/home/vscode/.aspnet/https/aspnetapp.pfx", + // }, + // + // 3. Next, copy your certificate into the container: + // 1. Start the container + // 2. Drag ~/.aspnet/https/aspnetapp.pfx into the root of the file explorer + // 3. Open a terminal in VS Code and run "mkdir -p /home/vscode/.aspnet/https && mv aspnetapp.pfx /home/vscode/.aspnet/https" + + // postCreateCommand.sh parameters: $1=SA password, $2=dacpac path, $3=sql script(s) path + "postCreateCommand": "bash .devcontainer/mssql/postCreateCommand.sh 'P@ssw0rd' './bin/Debug/' './.devcontainer/mssql/'" +} diff --git a/.devcontainer/docker-compose.yml b/.devcontainer/docker-compose.yml new file mode 100644 index 0000000000..17312c6bd8 --- /dev/null +++ b/.devcontainer/docker-compose.yml @@ -0,0 +1,115 @@ +version: '3' + +services: + app: + build: + context: . + dockerfile: Dockerfile + args: + # [Choice] Update 'VARIANT' to pick a .NET Core version: 2.1, 3.1, 5.0 + VARIANT: 5.0 + # Options + INSTALL_NODE: "true" + NODE_VERSION: "lts/*" + INSTALL_AZURE_CLI: "false" + # On Linux, you may need to update USER_UID and USER_GID below if not your local UID is not 1000. + USER_UID: 1000 + USER_GID: 1000 + + volumes: + - ..:/workspace:cached + + # Overrides default command so things don't shut down after the process ends. + command: sleep infinity + + # Runs app on the same network as the database container, allows "forwardPorts" in devcontainer.json function. + network_mode: service:db + + # Uncomment the next line to use a non-root user for all processes. + # user: vscode + + # Use "forwardPorts" in **devcontainer.json** to forward an app port locally. + # (Adding the "ports" property to this file will not forward from a Codespace.) + + # DotNetCore ENV Variables + # https://docs.microsoft.com/en-us/aspnet/core/fundamentals/configuration/?view=aspnetcore-5.0#environment-variables + environment: + - ConnectionStrings__umbracoDbDSN=server=localhost;database=UmbracoUnicore;user id=sa;password='P@ssw0rd' + - Umbraco__CMS__Unattended__InstallUnattended=true + - Umbraco__CMS__Unattended__UnattendedUserName=Admin + - Umbraco__CMS__Unattended__UnattendedUserEmail=test@umbraco.com + - Umbraco__CMS__Unattended__UnattendedUserPassword=password1234 + - Umbraco__CMS__Global__Smtp__Host=smtp4dev + - Umbraco__CMS__Global__Smtp__Port=25 + - Umbraco__CMS__Global__Smtp__From=warren-env@umbraco.com + + db: + image: mcr.microsoft.com/mssql/server:2019-latest + restart: unless-stopped + environment: + SA_PASSWORD: P@ssw0rd + ACCEPT_EULA: Y + + # Add "forwardPorts": ["1433"] to **devcontainer.json** to forward MSSQL locally. + # (Adding the "ports" property to this file will not forward from a Codespace.) + + smtp4dev: + image: rnwood/smtp4dev:v3 + restart: always + ports: + # Change the number before : to the port the web interface should be accessible on + - '5000:80' + # Change the number before : to the port the SMTP server should be accessible on + - '25:25' + # Change the number before : to the port the IMAP server should be accessible on + # - '143:143' + volumes: + # This is where smtp4dev stores the database.. + - smtp4dev-data:/smtp4dev + environment: + # Uncomment to customise these settings + + #Specifies the virtual path from web server root where SMTP4DEV web interface will be hosted. e.g. "/" or "/smtp4dev" + #- ServerOptions__BasePath=/smtp4dev + + #Specifies the server hostname. Used in auto-generated TLS certificate if enabled. + - ServerOptions__HostName=smtp4dev + + #Specifies the path where the database will be stored relative to APPDATA env var on Windows or XDG_CONFIG_HOME on non-Windows. Specify "" to use an in memory database. + #- ServerOptions__Database=database.db + + #Specifies the number of messages to keep + #- ServerOptions__NumberOfMessagesToKeep=100 + + #Specifies the number of sessions to keep + #- ServerOptions__NumberOfSessionsToKeep=100 + + #Specifies the TLS mode to use. None=Off. StartTls=On demand if client supports STARTTLS. ImplicitTls=TLS as soon as connection is established. + #- ServerOptions__TlsMode=None + + #Specifies the TLS certificate to use if TLS is enabled/requested. Specify "" to use an auto-generated self-signed certificate (then see console output on first startup) + #- ServerOptions__TlsCertificate= + + #Sets the name of the SMTP server that will be used to relay messages or "" if messages should not be relayed + #- RelayOptions__SmtpServer= + + #Sets the port number for the SMTP server used to relay messages. + #- RelayOptions__SmtpPort=25 + + #Specifies a comma separated list of recipient addresses for which messages will be relayed. An empty list means that no messages are relayed. + #- RelayOptions__AllowedEmailsString= + + #Specifies the address used in MAIL FROM when relaying messages. (Sender address in message headers is left unmodified). The sender of each message is used if not specified. + #- RelayOptions__SenderAddress= + + #The username for the SMTP server used to relay messages. If "" no authentication is attempted. + #- RelayOptions__Login= + + #The password for the SMTP server used to relay messages + #- RelayOptions__Password= + + #Specifies the port the IMAP server will listen on - allows standard email clients to view/retrieve messages + #"ServerOptions__ImapPort": 143 + +volumes: + smtp4dev-data: diff --git a/.devcontainer/library-scripts/azcli-debian.sh b/.devcontainer/library-scripts/azcli-debian.sh new file mode 100644 index 0000000000..b03dcb0f04 --- /dev/null +++ b/.devcontainer/library-scripts/azcli-debian.sh @@ -0,0 +1,33 @@ +#!/usr/bin/env bash +#------------------------------------------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See https://go.microsoft.com/fwlink/?linkid=2090316 for license information. +#------------------------------------------------------------------------------------------------------------- +# +# Docs: https://github.com/microsoft/vscode-dev-containers/blob/master/script-library/docs/azcli.md +# +# Syntax: ./azcli-debian.sh + +set -e + +if [ "$(id -u)" -ne 0 ]; then + echo -e 'Script must be run as root. Use sudo, su, or add "USER root" to your Dockerfile before running this script.' + exit 1 +fi + +export DEBIAN_FRONTEND=noninteractive + +# Install curl, apt-transport-https, lsb-release, or gpg if missing +if ! dpkg -s apt-transport-https curl ca-certificates lsb-release > /dev/null 2>&1 || ! type gpg > /dev/null 2>&1; then + if [ ! -d "/var/lib/apt/lists" ] || [ "$(ls /var/lib/apt/lists/ | wc -l)" = "0" ]; then + apt-get update + fi + apt-get -y install --no-install-recommends apt-transport-https curl ca-certificates lsb-release gnupg2 +fi + +# Install the Azure CLI +echo "deb [arch=amd64] https://packages.microsoft.com/repos/azure-cli/ $(lsb_release -cs) main" > /etc/apt/sources.list.d/azure-cli.list +curl -sL https://packages.microsoft.com/keys/microsoft.asc | (OUT=$(apt-key add - 2>&1) || echo $OUT) +apt-get update +apt-get install -y azure-cli +echo "Done!" \ No newline at end of file diff --git a/.devcontainer/mssql/BlankDb.sql b/.devcontainer/mssql/BlankDb.sql new file mode 100644 index 0000000000..44546efebf --- /dev/null +++ b/.devcontainer/mssql/BlankDb.sql @@ -0,0 +1,11 @@ +/* + This will generate a blank database when the container is spun up + that you can use to connect to for the SQL configuration in the web installer flow + + ---- NOTE ---- + Any .sql files in this folder will be executed + Along with any .dacpac will be restored as databases + See postCreateCommand.sh for specifics +*/ +CREATE DATABASE UmbracoUnicore; +GO \ No newline at end of file diff --git a/.devcontainer/mssql/installSQLtools.sh b/.devcontainer/mssql/installSQLtools.sh new file mode 100644 index 0000000000..3fa6a67a09 --- /dev/null +++ b/.devcontainer/mssql/installSQLtools.sh @@ -0,0 +1,16 @@ +#!/bin/bash +set -echo +echo "Installing mssql-tools" +curl -sSL https://packages.microsoft.com/keys/microsoft.asc | (OUT=$(apt-key add - 2>&1) || echo $OUT) +DISTRO=$(lsb_release -is | tr '[:upper:]' '[:lower:]') +CODENAME=$(lsb_release -cs) +echo "deb [arch=amd64] https://packages.microsoft.com/repos/microsoft-${DISTRO}-${CODENAME}-prod ${CODENAME} main" > /etc/apt/sources.list.d/microsoft.list +apt-get update +ACCEPT_EULA=Y apt-get -y install unixodbc-dev msodbcsql17 libunwind8 mssql-tools + +echo "Installing sqlpackage" +curl -sSL -o sqlpackage.zip "https://aka.ms/sqlpackage-linux" +mkdir /opt/sqlpackage +unzip sqlpackage.zip -d /opt/sqlpackage +rm sqlpackage.zip +chmod a+x /opt/sqlpackage/sqlpackage diff --git a/.devcontainer/mssql/postCreateCommand.sh b/.devcontainer/mssql/postCreateCommand.sh new file mode 100644 index 0000000000..e25583e0ff --- /dev/null +++ b/.devcontainer/mssql/postCreateCommand.sh @@ -0,0 +1,64 @@ +#!/bin/bash +dacpac="false" +sqlfiles="false" +SApassword=$1 +dacpath=$2 +sqlpath=$3 + +echo "SELECT * FROM SYS.DATABASES" | dd of=testsqlconnection.sql +for i in {1..60}; +do + /opt/mssql-tools/bin/sqlcmd -S localhost -U sa -P $SApassword -d master -i testsqlconnection.sql > /dev/null + if [ $? -eq 0 ] + then + echo "SQL server ready" + break + else + echo "Not ready yet..." + sleep 1 + fi +done +rm testsqlconnection.sql + +for f in $dacpath/* +do + if [ $f == $dacpath/*".dacpac" ] + then + dacpac="true" + echo "Found dacpac $f" + fi +done + +for f in $sqlpath/* +do + if [ $f == $sqlpath/*".sql" ] + then + sqlfiles="true" + echo "Found SQL file $f" + fi +done + +if [ $sqlfiles == "true" ] +then + for f in $sqlpath/* + do + if [ $f == $sqlpath/*".sql" ] + then + echo "Executing $f" + /opt/mssql-tools/bin/sqlcmd -S localhost -U sa -P $SApassword -d master -i $f + fi + done +fi + +if [ $dacpac == "true" ] +then + for f in $dacpath/* + do + if [ $f == $dacpath/*".dacpac" ] + then + dbname=$(basename $f ".dacpac") + echo "Deploying dacpac $f" + /opt/sqlpackage/sqlpackage /Action:Publish /SourceFile:$f /TargetServerName:localhost /TargetDatabaseName:$dbname /TargetUser:sa /TargetPassword:$SApassword + fi + done +fi \ No newline at end of file diff --git a/.gitignore b/.gitignore index 1c54100176..c792b2c5a9 100644 --- a/.gitignore +++ b/.gitignore @@ -103,6 +103,7 @@ src/Umbraco.Web.UI/[Uu]mbraco/[Jj]s/canvasdesigner.*.js src/Umbraco.Web.UI/[Uu]mbraco/[Jj]s/navigation.controller.js src/Umbraco.Web.UI/[Uu]mbraco/[Jj]s/main.controller.js src/Umbraco.Web.UI/[Uu]mbraco/[Jj]s/utilities.js +src/Umbraco.Web.UI/[Uu]mbraco/[Jj]s/installer.app.js src/Umbraco.Web.UI/[Uu]mbraco/[Vv]iews/ src/Umbraco.Web.UI/[Uu]mbraco/[Vv]iews/**/*.js @@ -180,16 +181,19 @@ src/Umbraco.Web.UI/Umbraco/telemetrics-id.umb /src/Umbraco.Web.UI.NetCore/wwwroot/is-cache/* /src/Umbraco.Tests.Integration/App_Data/* /src/Umbraco.Tests.Integration/TEMP/* -/src/Umbraco.Web.UI.NetCore/wwwroot/Umbraco/assets/* -/src/Umbraco.Web.UI.NetCore/wwwroot/Umbraco/js/* -/src/Umbraco.Web.UI.NetCore/wwwroot/Umbraco/lib/* -/src/Umbraco.Web.UI.NetCore/wwwroot/Umbraco/views/* +/src/Umbraco.Web.UI.NetCore/wwwroot/[Uu]mbraco/assets/* +/src/Umbraco.Web.UI.NetCore/wwwroot/[Uu]mbraco/js/* +/src/Umbraco.Web.UI.NetCore/wwwroot/[Uu]mbraco/lib/* +/src/Umbraco.Web.UI.NetCore/wwwroot/[Uu]mbraco/views/* /src/Umbraco.Web.UI.NetCore/wwwroot/App_Data/TEMP/* /src/Umbraco.Web.UI.NetCore/App_Data/Logs/* /src/Umbraco.Web.UI.NetCore/App_Data/TEMP/TypesCache/* /src/Umbraco.Web.UI.NetCore/App_Data/TEMP/* /src/Umbraco.Web.UI.NetCore/App_Data/Smidge/Cache/* -/src/Umbraco.Web.UI.NetCore/umbraco/logs +/src/Umbraco.Web.UI.NetCore/[Uu]mbraco/[Ll]ogs +/src/Umbraco.Web.UI.NetCore/[Uu]mbraco/[Dd]ata/* +/src/Umbraco.Web.UI.NetCore/[Uu]mbraco/[Mm]odels/* + src/Umbraco.Tests.Integration/umbraco/Data/ src/Umbraco.Tests.Integration/umbraco/logs/ @@ -197,10 +201,11 @@ src/Umbraco.Tests.Integration/umbraco/logs/ src/Umbraco.Tests.Integration/Views/ src/Umbraco.Tests/TEMP/ -/src/Umbraco.Web.UI.NetCore/Umbraco/Data/* + /src/Umbraco.Web.UI/config/umbracoSettings.config -/src/Umbraco.Web.UI.NetCore/Umbraco/models/* + src/Umbraco.Tests.UnitTests/umbraco/Data/TEMP/ /src/Umbraco.Web.UI.NetCore/appsettings.Local.json src/Umbraco.Tests.Integration/DatabaseContextTests.sdf + diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000000..85b28c51c1 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,36 @@ +{ + "version": "0.2.0", + "configurations": [ + { + // Use IntelliSense to find out which attributes exist for C# debugging + // Use hover for the description of the existing attributes + // For further information visit https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md + "name": ".NET Core Launch (web)", + "type": "coreclr", + "request": "launch", + "preLaunchTask": "Dotnet build", + // If you have changed target frameworks, make sure to update the program path. + "program": "${workspaceFolder}/src/Umbraco.Web.UI.NetCore/bin/Debug/net5.0/Umbraco.Web.UI.NetCore.dll", + "args": [], + "cwd": "${workspaceFolder}/src/Umbraco.Web.UI.NetCore", + "stopAtEntry": false, + // Enable launching a web browser when ASP.NET Core starts. For more information: https://aka.ms/VSCode-CS-LaunchJson-WebBrowser + "serverReadyAction": { + "action": "openExternally", + "pattern": "\\\\bNow listening on:\\\\s+(https?://\\\\S+)" + }, + "env": { + "ASPNETCORE_ENVIRONMENT": "Development" + }, + "sourceFileMap": { + "/Views": "${workspaceFolder}/Views" + } + }, + { + "name": ".NET Core Attach", + "type": "coreclr", + "request": "attach", + "processId": "${command:pickProcess}" + } + ] +} \ No newline at end of file diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 0000000000..e2b6c01894 --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,67 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "label": "Build", + "detail": "Builds the client and SLN", + "promptOnClose": true, + "group": "build", + "dependsOn": [ + "Client Build", + "Dotnet build" + ], + "problemMatcher": [] + }, + { + "label": "Client Install", + "detail": "install npm for Umbraco.Web.UI.Client", + "promptOnClose": true, + "type": "npm", + "script": "install", + "path": "src/Umbraco.Web.UI.Client/", + "problemMatcher": [] + }, + { + "label": "Client Build", + "detail": "runs npm run build for Umbraco.Web.UI.Client", + "promptOnClose": true, + "group": "build", + "type": "npm", + "script": "build", + "path": "src/Umbraco.Web.UI.Client/", + "problemMatcher": [ + "$gulp-tsc" + ] + }, + { + "label": "Dotnet build", + "detail": "Dotnet build of SLN", + "promptOnClose": true, + "group": "build", + "command": "dotnet", + "type": "process", + "args": [ + "build", + "${workspaceFolder}/src/umbraco-netcore-only.sln", + "/property:GenerateFullPaths=true", + "/consoleloggerparameters:NoSummary" + ], + "problemMatcher": "$msCompile" + }, + { + "label": "Dotnet watch", + "detail": "Dotnet run and watch of Web.UI.NetCore", + "promptOnClose": true, + "command": "dotnet", + "type": "process", + "args": [ + "watch", + "run", + "${workspaceFolder}/src/Umbraco.Web.UI.NetCore/Umbraco.Web.UI.NetCore.csproj", + "/property:GenerateFullPaths=true", + "/consoleloggerparameters:NoSummary" + ], + "problemMatcher": "$msCompile" + } + ] +} \ No newline at end of file diff --git a/src/Umbraco.Tests.UnitTests/Umbraco.Core/Routing/ContentFinderByUrlAliasTests.cs b/src/Umbraco.Tests.UnitTests/Umbraco.Core/Routing/ContentFinderByUrlAliasTests.cs new file mode 100644 index 0000000000..d4c1e303e9 --- /dev/null +++ b/src/Umbraco.Tests.UnitTests/Umbraco.Core/Routing/ContentFinderByUrlAliasTests.cs @@ -0,0 +1,63 @@ +using System; +using AutoFixture.NUnit3; +using Moq; +using NUnit.Framework; +using Umbraco.Cms.Core; +using Umbraco.Cms.Core.Models.PublishedContent; +using Umbraco.Cms.Core.PublishedCache; +using Umbraco.Cms.Core.Routing; +using Umbraco.Cms.Core.Services; +using Umbraco.Cms.Core.Web; +using Umbraco.Cms.Tests.UnitTests.AutoFixture; + +namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Core.Routing +{ + [TestFixture] + public class ContentFinderByUrlAliasTests + { + + [Test] + [InlineAutoMoqData("/this/is/my/alias", 1001)] + [InlineAutoMoqData("/anotheralias", 1001)] + [InlineAutoMoqData("/page2/alias", 10011)] + [InlineAutoMoqData("/2ndpagealias", 10011)] + [InlineAutoMoqData("/only/one/alias", 100111)] + [InlineAutoMoqData("/ONLY/one/Alias", 100111)] + [InlineAutoMoqData("/alias43", 100121)] + public void Lookup_By_Url_Alias ( + string relativeUrl, + int nodeMatch, + [Frozen] IPublishedContentCache publishedContentCache, + [Frozen] IUmbracoContextAccessor umbracoContextAccessor, + [Frozen] IUmbracoContext umbracoContext, + [Frozen] IVariationContextAccessor variationContextAccessor, + IFileService fileService, + ContentFinderByUrlAlias sut, + IPublishedContent[] rootContents, + IPublishedProperty urlProperty + ) + { + + + //Arrange + var absoluteUrl = "http://localhost" + relativeUrl; + VariationContext variationContext = new VariationContext(); + + var contentItem = rootContents[0]; + Mock.Get(umbracoContextAccessor).Setup(x => x.UmbracoContext).Returns(umbracoContext); + Mock.Get(umbracoContext).Setup(x => x.Content).Returns(publishedContentCache); + Mock.Get(publishedContentCache).Setup(x => x.GetAtRoot(null)).Returns(rootContents); + Mock.Get(contentItem).Setup(x => x.Id).Returns(nodeMatch); + Mock.Get(contentItem).Setup(x => x.GetProperty(Constants.Conventions.Content.UrlAlias)).Returns(urlProperty); + Mock.Get(urlProperty).Setup(x => x.GetValue(null, null)).Returns(relativeUrl); + + Mock.Get(variationContextAccessor).Setup(x => x.VariationContext).Returns(variationContext); + var publishedRequestBuilder = new PublishedRequestBuilder(new Uri(absoluteUrl, UriKind.Absolute), fileService); + //Act + var result = sut.TryFindContent(publishedRequestBuilder); + + Assert.IsTrue(result); + Assert.AreEqual(publishedRequestBuilder.PublishedContent.Id, nodeMatch); + } + } +}