Added vitest | added dockerfile | wrote some tests
This commit is contained in:
parent
1fd30f1a16
commit
54c2539b2a
25
.dockerignore
Normal file
25
.dockerignore
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
**/.dockerignore
|
||||||
|
**/.env
|
||||||
|
**/.git
|
||||||
|
**/.gitignore
|
||||||
|
**/.project
|
||||||
|
**/.settings
|
||||||
|
**/.toolstarget
|
||||||
|
**/.vs
|
||||||
|
**/.vscode
|
||||||
|
**/.idea
|
||||||
|
**/*.*proj.user
|
||||||
|
**/*.dbmdl
|
||||||
|
**/*.jfm
|
||||||
|
**/azds.yaml
|
||||||
|
**/bin
|
||||||
|
**/charts
|
||||||
|
**/docker-compose*
|
||||||
|
**/Dockerfile*
|
||||||
|
**/node_modules
|
||||||
|
**/npm-debug.log
|
||||||
|
**/obj
|
||||||
|
**/secrets.dev.yaml
|
||||||
|
**/values.dev.yaml
|
||||||
|
LICENSE
|
||||||
|
README.md
|
11
.run/All Tests.run.xml
Normal file
11
.run/All Tests.run.xml
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
<component name="ProjectRunConfigurationManager">
|
||||||
|
<configuration default="false" name="All Tests" type="JavaScriptTestRunnerVitest" nameIsGenerated="true">
|
||||||
|
<node-interpreter value="project" />
|
||||||
|
<vitest-package value="$PROJECT_DIR$/pac-man-board-game/ClientApp/node_modules/vitest" />
|
||||||
|
<working-dir value="$PROJECT_DIR$" />
|
||||||
|
<vitest-options value="--environment happy-dom" />
|
||||||
|
<envs />
|
||||||
|
<scope-kind value="ALL" />
|
||||||
|
<method v="2" />
|
||||||
|
</configuration>
|
||||||
|
</component>
|
7
global.json
Normal file
7
global.json
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"sdk": {
|
||||||
|
"version": "7.0.0",
|
||||||
|
"rollForward": "latestMajor",
|
||||||
|
"allowPrerelease": true
|
||||||
|
}
|
||||||
|
}
|
1
pac-man-board-game/ClientApp/.gitignore
vendored
1
pac-man-board-game/ClientApp/.gitignore
vendored
@ -8,6 +8,7 @@
|
|||||||
|
|
||||||
# production
|
# production
|
||||||
/build
|
/build
|
||||||
|
/dist
|
||||||
|
|
||||||
# misc
|
# misc
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
File diff suppressed because it is too large
Load Diff
1324
pac-man-board-game/ClientApp/package-lock.json
generated
1324
pac-man-board-game/ClientApp/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "pac_man_board_game",
|
"name": "pac_man_board_game",
|
||||||
"version": "0.1-Testing",
|
"version": "0.1.1",
|
||||||
"private": true,
|
"private": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@headlessui/react": "^1.7.14",
|
"@headlessui/react": "^1.7.14",
|
||||||
@ -14,7 +14,6 @@
|
|||||||
"web-vitals": "^2.1.4"
|
"web-vitals": "^2.1.4"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/jest": "^29.5.1",
|
|
||||||
"@types/react": "^18.2.6",
|
"@types/react": "^18.2.6",
|
||||||
"@types/react-dom": "^18.2.4",
|
"@types/react-dom": "^18.2.4",
|
||||||
"@vitejs/plugin-react": "^4.0.0",
|
"@vitejs/plugin-react": "^4.0.0",
|
||||||
@ -27,13 +26,15 @@
|
|||||||
"eslint-plugin-import": "^2.27.5",
|
"eslint-plugin-import": "^2.27.5",
|
||||||
"eslint-plugin-jsx-a11y": "^6.7.1",
|
"eslint-plugin-jsx-a11y": "^6.7.1",
|
||||||
"eslint-plugin-react": "^7.32.2",
|
"eslint-plugin-react": "^7.32.2",
|
||||||
|
"happy-dom": "^9.20.1",
|
||||||
"nan": "^2.17.0",
|
"nan": "^2.17.0",
|
||||||
"postcss": "^8.4.23",
|
"postcss": "^8.4.23",
|
||||||
"tailwindcss": "^3.3.2",
|
"tailwindcss": "^3.3.2",
|
||||||
"typescript": "^5.0.4",
|
"typescript": "^5.0.4",
|
||||||
"vite": "^4.3.6",
|
"vite": "^4.3.6",
|
||||||
"vite-plugin-svgr": "^3.2.0",
|
"vite-plugin-svgr": "^3.2.0",
|
||||||
"vite-tsconfig-paths": "^4.2.0"
|
"vite-tsconfig-paths": "^4.2.0",
|
||||||
|
"vitest": "^0.31.1"
|
||||||
},
|
},
|
||||||
"resolutions": {
|
"resolutions": {
|
||||||
"css-what": "^5.0.1",
|
"css-what": "^5.0.1",
|
||||||
@ -44,7 +45,8 @@
|
|||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
"build": "vite build",
|
"build": "vite build",
|
||||||
"serve": "vite preview",
|
"serve": "vite preview",
|
||||||
"test": "cross-env CI=true react-scripts test --env=jsdom",
|
"test": "cross-env CI=true vitest",
|
||||||
|
"coverage": "vitest run --coverage",
|
||||||
"lint": "eslint ./src/"
|
"lint": "eslint ./src/"
|
||||||
},
|
},
|
||||||
"eslintConfig": {
|
"eslintConfig": {
|
||||||
|
@ -2,28 +2,7 @@ import React, {useEffect, useState} from "react";
|
|||||||
import {Character, PacMan} from "../game/character";
|
import {Character, PacMan} from "../game/character";
|
||||||
import findPossiblePositions from "../game/possibleMovesAlgorithm";
|
import findPossiblePositions from "../game/possibleMovesAlgorithm";
|
||||||
import {TileType} from "../game/tileType";
|
import {TileType} from "../game/tileType";
|
||||||
|
import {testMap} from "../game/map";
|
||||||
/**
|
|
||||||
* 0 = empty
|
|
||||||
* 1 = wall
|
|
||||||
* 2 = pellet
|
|
||||||
* 3 = power pellet
|
|
||||||
* 4 = ghost spawn
|
|
||||||
* 5 = pacman spawn
|
|
||||||
*/
|
|
||||||
const map: number[][] = [
|
|
||||||
[1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1],
|
|
||||||
[1, 2, 0, 0, 0, 2, 0, 0, 0, 2, 1],
|
|
||||||
[1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1],
|
|
||||||
[1, 0, 1, 5, 1, 0, 1, 4, 1, 0, 1],
|
|
||||||
[1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1],
|
|
||||||
[0, 2, 0, 0, 0, 3, 0, 0, 0, 2, 0],
|
|
||||||
[1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1],
|
|
||||||
[1, 0, 1, 4, 1, 0, 1, 5, 1, 0, 1],
|
|
||||||
[1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1],
|
|
||||||
[1, 2, 0, 0, 0, 2, 0, 0, 0, 2, 1],
|
|
||||||
[1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1],
|
|
||||||
];
|
|
||||||
|
|
||||||
interface BoardProps extends ComponentProps {
|
interface BoardProps extends ComponentProps {
|
||||||
characters: Character[],
|
characters: Character[],
|
||||||
@ -58,7 +37,7 @@ const Board: Component<BoardProps> = (
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (selectedCharacter && selectedDice) {
|
if (selectedCharacter && selectedDice) {
|
||||||
const possiblePositions = findPossiblePositions(map, selectedCharacter, selectedDice.value);
|
const possiblePositions = findPossiblePositions(testMap, selectedCharacter, selectedDice.value);
|
||||||
setPossiblePositions(possiblePositions);
|
setPossiblePositions(possiblePositions);
|
||||||
} else {
|
} else {
|
||||||
setPossiblePositions([]);
|
setPossiblePositions([]);
|
||||||
@ -89,7 +68,7 @@ const Board: Component<BoardProps> = (
|
|||||||
return (
|
return (
|
||||||
<div className={`w-fit ${className}`}>
|
<div className={`w-fit ${className}`}>
|
||||||
{
|
{
|
||||||
map.map((row, rowIndex) =>
|
testMap.map((row, rowIndex) =>
|
||||||
<div key={rowIndex} className={"flex"}>
|
<div key={rowIndex} className={"flex"}>
|
||||||
{
|
{
|
||||||
row.map((tile, colIndex) =>
|
row.map((tile, colIndex) =>
|
||||||
|
21
pac-man-board-game/ClientApp/src/game/map.ts
Normal file
21
pac-man-board-game/ClientApp/src/game/map.ts
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
/**
|
||||||
|
* 0 = empty
|
||||||
|
* 1 = wall
|
||||||
|
* 2 = pellet
|
||||||
|
* 3 = power pellet
|
||||||
|
* 4 = ghost spawn
|
||||||
|
* 5 = pacman spawn
|
||||||
|
*/
|
||||||
|
export const testMap: GameMap = [
|
||||||
|
[1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1],
|
||||||
|
[1, 2, 0, 0, 0, 2, 0, 0, 0, 2, 1],
|
||||||
|
[1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1],
|
||||||
|
[1, 0, 1, 5, 1, 0, 1, 4, 1, 0, 1],
|
||||||
|
[1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1],
|
||||||
|
[0, 2, 0, 0, 0, 3, 0, 0, 0, 2, 0],
|
||||||
|
[1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1],
|
||||||
|
[1, 0, 1, 4, 1, 0, 1, 5, 1, 0, 1],
|
||||||
|
[1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1],
|
||||||
|
[1, 2, 0, 0, 0, 2, 0, 0, 0, 2, 1],
|
||||||
|
[1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1],
|
||||||
|
];
|
@ -7,13 +7,13 @@ import {Character} from "./character";
|
|||||||
* @param character The current position of the character
|
* @param character The current position of the character
|
||||||
* @param steps The number of steps the character can move
|
* @param steps The number of steps the character can move
|
||||||
*/
|
*/
|
||||||
export default function findPossiblePositions(board: number[][], character: Character, steps: number): Position[] {
|
export default function findPossiblePositions(board: GameMap, character: Character, steps: number): Position[] {
|
||||||
const possiblePositions: Position[] = [];
|
const possiblePositions: Position[] = [];
|
||||||
findPossibleRecursive(board, character.position, steps, possiblePositions, []);
|
findPossibleRecursive(board, character.position, steps, possiblePositions, []);
|
||||||
return possiblePositions;
|
return possiblePositions;
|
||||||
}
|
}
|
||||||
|
|
||||||
function findPossibleRecursive(board: number[][], currentPos: Position, steps: number,
|
function findPossibleRecursive(board: GameMap, currentPos: Position, steps: number,
|
||||||
possibleList: Position[], visitedTiles: Position[]): Position | null {
|
possibleList: Position[], visitedTiles: Position[]): Position | null {
|
||||||
if (isOutsideBoard(currentPos, board.length)) {
|
if (isOutsideBoard(currentPos, board.length)) {
|
||||||
addTeleportationTiles(board, currentPos, steps, possibleList, visitedTiles);
|
addTeleportationTiles(board, currentPos, steps, possibleList, visitedTiles);
|
||||||
|
@ -15,3 +15,5 @@ type SelectedDice = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
type Position = { x: number, y: number };
|
type Position = { x: number, y: number };
|
||||||
|
|
||||||
|
type GameMap = number[][];
|
||||||
|
@ -22,6 +22,7 @@ export default class WebSocketService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public open(): void {
|
public open(): void {
|
||||||
|
if (typeof WebSocket === "undefined") return;
|
||||||
this.ws = new WebSocket(this._url);
|
this.ws = new WebSocket(this._url);
|
||||||
if (this._onOpen) this.ws.onopen = this._onOpen;
|
if (this._onOpen) this.ws.onopen = this._onOpen;
|
||||||
if (this._onReceive) this.ws.onmessage = this._onReceive;
|
if (this._onReceive) this.ws.onmessage = this._onReceive;
|
||||||
@ -65,7 +66,7 @@ export default class WebSocketService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public isOpen(): boolean {
|
public isOpen(): boolean {
|
||||||
return this.ws?.readyState === WebSocket.OPEN;
|
return this.ws?.readyState === WebSocket?.OPEN;
|
||||||
}
|
}
|
||||||
|
|
||||||
set onOpen(onOpen: VoidFunction) {
|
set onOpen(onOpen: VoidFunction) {
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import {createRoot} from "react-dom/client";
|
import {createRoot} from "react-dom/client";
|
||||||
import {MemoryRouter} from "react-router-dom";
|
import {MemoryRouter} from "react-router-dom";
|
||||||
import {App} from "./App";
|
import {App} from "../src/App";
|
||||||
|
import {it} from "vitest";
|
||||||
|
|
||||||
it("renders without crashing", async () => {
|
it("renders without crashing", async () => {
|
||||||
const div = document.createElement("div");
|
const div = document.createElement("div");
|
@ -0,0 +1,59 @@
|
|||||||
|
import {test, expect, beforeEach} from "vitest";
|
||||||
|
import possibleMovesAlgorithm from "../../src/game/possibleMovesAlgorithm";
|
||||||
|
import {testMap} from "../../src/game/map";
|
||||||
|
import {Character, PacMan} from "../../src/game/character";
|
||||||
|
|
||||||
|
let pacMan: Character;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
pacMan = new PacMan("yellow", {x: 3, y: 3});
|
||||||
|
});
|
||||||
|
|
||||||
|
test("One from start, should return one position", () => {
|
||||||
|
const result = possibleMovesAlgorithm(testMap, pacMan, 1);
|
||||||
|
expect(result).toEqual([{x: 3, y: 2}]);
|
||||||
|
expect(result.length).toBe(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Two from start, should return one position", () => {
|
||||||
|
const result = possibleMovesAlgorithm(testMap, pacMan, 2);
|
||||||
|
expect(result).toEqual([{x: 3, y: 1}]);
|
||||||
|
expect(result.length).toBe(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Three from start, should return two positions", () => {
|
||||||
|
const result = possibleMovesAlgorithm(testMap, pacMan, 3);
|
||||||
|
arrayEquals(result, [{x: 2, y: 1}, {x: 4, y: 1}]);
|
||||||
|
expect(result.length).toBe(2);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Four from start, should return two positions", () => {
|
||||||
|
const result = possibleMovesAlgorithm(testMap, pacMan, 4);
|
||||||
|
arrayEquals(result, [{x: 1, y: 1}, {x: 5, y: 1}]);
|
||||||
|
expect(result.length).toBe(2);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Five from start, should return four positions", () => {
|
||||||
|
const result = possibleMovesAlgorithm(testMap, pacMan, 5);
|
||||||
|
arrayEquals(result, [{x: 5, y: 0}, {x: 6, y: 1}, {x: 1, y: 2}, {x: 5, y: 2}]);
|
||||||
|
expect(result.length).toBe(4);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Six from start, should return six positions", () => {
|
||||||
|
const result = possibleMovesAlgorithm(testMap, pacMan, 6);
|
||||||
|
arrayEquals(result, [{x: 1, y: 3}, {x: 0, y: 5}, {x: 5, y: 3}, {x: 7, y: 1}, {x: 10, y: 5}, {x: 5, y: 10}]);
|
||||||
|
expect(result.length).toBe(6);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Six from position [1,5], should return 14", () => {
|
||||||
|
pacMan.moveTo({x: 1, y: 5});
|
||||||
|
const result = possibleMovesAlgorithm(testMap, pacMan, 6);
|
||||||
|
// TODO add possible moves
|
||||||
|
expect(result.length).toBe(14);
|
||||||
|
});
|
||||||
|
|
||||||
|
function arrayEquals<T extends any[]>(result: T, expected: T, message?: string): void {
|
||||||
|
for (const item of expected) {
|
||||||
|
expect(result, message).toContainEqual(item);
|
||||||
|
}
|
||||||
|
}
|
@ -12,10 +12,10 @@
|
|||||||
"target": "ESNext",
|
"target": "ESNext",
|
||||||
"module": "ESNext",
|
"module": "ESNext",
|
||||||
"lib": ["dom", "dom.iterable", "esnext"],
|
"lib": ["dom", "dom.iterable", "esnext"],
|
||||||
"types": ["vite/client", "vite-plugin-svgr/client", "jest"],
|
"types": ["vite/client", "vite-plugin-svgr/client"],
|
||||||
"moduleResolution": "node",
|
"moduleResolution": "node",
|
||||||
},
|
},
|
||||||
"include": [
|
"include": [
|
||||||
"src"
|
"src", "tests"
|
||||||
]
|
]
|
||||||
}
|
}
|
@ -9,6 +9,10 @@ import {execSync} from "child_process";
|
|||||||
|
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
plugins: [react()],
|
plugins: [react()],
|
||||||
|
test: {
|
||||||
|
globals: false,
|
||||||
|
environment: "happy-dom",
|
||||||
|
},
|
||||||
server: {
|
server: {
|
||||||
port: 3000,
|
port: 3000,
|
||||||
strictPort: true,
|
strictPort: true,
|
||||||
|
28
pac-man-board-game/Dockerfile
Normal file
28
pac-man-board-game/Dockerfile
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
FROM mcr.microsoft.com/dotnet/aspnet:7.0 AS base
|
||||||
|
WORKDIR /app
|
||||||
|
EXPOSE 80
|
||||||
|
EXPOSE 443
|
||||||
|
|
||||||
|
FROM mcr.microsoft.com/dotnet/sdk:7.0 AS build
|
||||||
|
|
||||||
|
# Install Node.js TODO use node 18?
|
||||||
|
RUN curl -fsSL https://deb.nodesource.com/setup_14.x | bash - \
|
||||||
|
&& apt-get install -y \
|
||||||
|
nodejs \
|
||||||
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
WORKDIR /src
|
||||||
|
COPY ["pac-man-board-game/pac-man-board-game.csproj", "pac-man-board-game/"]
|
||||||
|
RUN dotnet restore "pac-man-board-game/pac-man-board-game.csproj"
|
||||||
|
COPY . .
|
||||||
|
WORKDIR "/src/pac-man-board-game"
|
||||||
|
# TODO missing build files from frontend
|
||||||
|
RUN dotnet build "pac-man-board-game.csproj" -c Release -o /app/build
|
||||||
|
|
||||||
|
FROM build AS publish
|
||||||
|
RUN dotnet publish "pac-man-board-game.csproj" -c Release -o /app/publish /p:UseAppHost=false
|
||||||
|
|
||||||
|
FROM base AS final
|
||||||
|
WORKDIR /app
|
||||||
|
COPY --from=publish /app/publish .
|
||||||
|
ENTRYPOINT ["dotnet", "pac-man-board-game.dll"]
|
@ -24,6 +24,16 @@
|
|||||||
"ASPNETCORE_ENVIRONMENT": "Development",
|
"ASPNETCORE_ENVIRONMENT": "Development",
|
||||||
"ASPNETCORE_HOSTINGSTARTUPASSEMBLIES": "Microsoft.AspNetCore.SpaProxy"
|
"ASPNETCORE_HOSTINGSTARTUPASSEMBLIES": "Microsoft.AspNetCore.SpaProxy"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"Docker": {
|
||||||
|
"commandName": "Docker",
|
||||||
|
"launchBrowser": true,
|
||||||
|
"environmentVariables": {
|
||||||
|
"ASPNETCORE_ENVIRONMENT": "Development",
|
||||||
|
"ASPNETCORE_HOSTINGSTARTUPASSEMBLIES": "Microsoft.AspNetCore.SpaProxy"
|
||||||
|
},
|
||||||
|
"launchUrl": "https://localhost:3000",
|
||||||
|
"useSSL": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
<SpaProxyLaunchCommand>npm run dev</SpaProxyLaunchCommand>
|
<SpaProxyLaunchCommand>npm run dev</SpaProxyLaunchCommand>
|
||||||
<RootNamespace>pacMan</RootNamespace>
|
<RootNamespace>pacMan</RootNamespace>
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
@ -26,6 +27,9 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<!-- Don't publish the SPA source files, but do show them in the project files list -->
|
<!-- Don't publish the SPA source files, but do show them in the project files list -->
|
||||||
<Content Remove="$(SpaRoot)**" />
|
<Content Remove="$(SpaRoot)**" />
|
||||||
|
<Content Include="..\.dockerignore">
|
||||||
|
<Link>.dockerignore</Link>
|
||||||
|
</Content>
|
||||||
<None Remove="$(SpaRoot)**" />
|
<None Remove="$(SpaRoot)**" />
|
||||||
<None Include="$(SpaRoot)**" Exclude="$(SpaRoot)node_modules\**" />
|
<None Include="$(SpaRoot)**" Exclude="$(SpaRoot)node_modules\**" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
@ -39,6 +43,7 @@
|
|||||||
<TypeScriptCompile Remove="ClientApp\src\game\tileMap.ts" />
|
<TypeScriptCompile Remove="ClientApp\src\game\tileMap.ts" />
|
||||||
<TypeScriptCompile Remove="ClientApp\src\components\gameCanvas.tsx" />
|
<TypeScriptCompile Remove="ClientApp\src\components\gameCanvas.tsx" />
|
||||||
<TypeScriptCompile Remove="ClientApp\src\game\game.ts" />
|
<TypeScriptCompile Remove="ClientApp\src\game\game.ts" />
|
||||||
|
<TypeScriptCompile Remove="ClientApp\src\App.test.tsx" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<Target Name="DebugEnsureNodeEnv" BeforeTargets="Build" Condition=" '$(Configuration)' == 'Debug' And !Exists('$(SpaRoot)node_modules') ">
|
<Target Name="DebugEnsureNodeEnv" BeforeTargets="Build" Condition=" '$(Configuration)' == 'Debug' And !Exists('$(SpaRoot)node_modules') ">
|
||||||
|
Loading…
x
Reference in New Issue
Block a user