Initial commit
This commit is contained in:
34
apps/shop/eslint.config.mjs
Normal file
34
apps/shop/eslint.config.mjs
Normal file
@@ -0,0 +1,34 @@
|
||||
import nx from '@nx/eslint-plugin';
|
||||
import baseConfig from '../../eslint.config.mjs';
|
||||
|
||||
export default [
|
||||
...baseConfig,
|
||||
...nx.configs['flat/angular'],
|
||||
...nx.configs['flat/angular-template'],
|
||||
{
|
||||
files: ['**/*.ts'],
|
||||
rules: {
|
||||
'@angular-eslint/directive-selector': [
|
||||
'error',
|
||||
{
|
||||
type: 'attribute',
|
||||
prefix: 'app',
|
||||
style: 'camelCase',
|
||||
},
|
||||
],
|
||||
'@angular-eslint/component-selector': [
|
||||
'error',
|
||||
{
|
||||
type: 'element',
|
||||
prefix: 'app',
|
||||
style: 'kebab-case',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
files: ['**/*.html'],
|
||||
// Override or add rules here
|
||||
rules: {},
|
||||
},
|
||||
];
|
||||
88
apps/shop/project.json
Normal file
88
apps/shop/project.json
Normal file
@@ -0,0 +1,88 @@
|
||||
{
|
||||
"name": "shop",
|
||||
"$schema": "../../node_modules/nx/schemas/project-schema.json",
|
||||
"projectType": "application",
|
||||
"prefix": "app",
|
||||
"sourceRoot": "apps/shop/src",
|
||||
"tags": ["scope:shop"],
|
||||
"targets": {
|
||||
"build": {
|
||||
"executor": "@angular/build:application",
|
||||
"outputs": ["{options.outputPath}"],
|
||||
"options": {
|
||||
"outputPath": "dist/apps/shop",
|
||||
"browser": "apps/shop/src/main.ts",
|
||||
"polyfills": ["zone.js"],
|
||||
"tsConfig": "apps/shop/tsconfig.app.json",
|
||||
"assets": [
|
||||
{
|
||||
"glob": "**/*",
|
||||
"input": "apps/shop/public"
|
||||
}
|
||||
],
|
||||
"styles": ["apps/shop/src/styles.css"],
|
||||
"server": "apps/shop/src/main.server.ts",
|
||||
"ssr": {
|
||||
"entry": "apps/shop/src/server.ts"
|
||||
},
|
||||
"outputMode": "server"
|
||||
},
|
||||
"configurations": {
|
||||
"production": {
|
||||
"budgets": [
|
||||
{
|
||||
"type": "initial",
|
||||
"maximumWarning": "500kb",
|
||||
"maximumError": "1mb"
|
||||
},
|
||||
{
|
||||
"type": "anyComponentStyle",
|
||||
"maximumWarning": "4kb",
|
||||
"maximumError": "8kb"
|
||||
}
|
||||
],
|
||||
"outputHashing": "all"
|
||||
},
|
||||
"development": {
|
||||
"optimization": false,
|
||||
"extractLicenses": false,
|
||||
"sourceMap": true
|
||||
}
|
||||
},
|
||||
"defaultConfiguration": "production"
|
||||
},
|
||||
"serve": {
|
||||
"dependsOn": ["api:serve"],
|
||||
"continuous": true,
|
||||
"executor": "@angular/build:dev-server",
|
||||
"configurations": {
|
||||
"production": {
|
||||
"buildTarget": "shop:build:production"
|
||||
},
|
||||
"development": {
|
||||
"buildTarget": "shop:build:development"
|
||||
}
|
||||
},
|
||||
"defaultConfiguration": "development",
|
||||
"options": {
|
||||
"proxyConfig": "apps/shop/proxy.conf.json"
|
||||
}
|
||||
},
|
||||
"extract-i18n": {
|
||||
"executor": "@angular/build:extract-i18n",
|
||||
"options": {
|
||||
"buildTarget": "shop:build"
|
||||
}
|
||||
},
|
||||
"serve-static": {
|
||||
"continuous": true,
|
||||
"executor": "@nx/web:file-server",
|
||||
"options": {
|
||||
"buildTarget": "shop:build",
|
||||
"port": 4200,
|
||||
"staticFilePath": "dist/apps/shop/browser",
|
||||
"spa": true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
6
apps/shop/proxy.conf.json
Normal file
6
apps/shop/proxy.conf.json
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"/@org/api": {
|
||||
"target": "http://localhost:3333",
|
||||
"secure": false
|
||||
}
|
||||
}
|
||||
BIN
apps/shop/public/favicon.ico
Normal file
BIN
apps/shop/public/favicon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 15 KiB |
10
apps/shop/src/app/app.config.server.ts
Normal file
10
apps/shop/src/app/app.config.server.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
import { mergeApplicationConfig, ApplicationConfig } from '@angular/core';
|
||||
import { provideServerRendering, withRoutes } from '@angular/ssr';
|
||||
import { appConfig } from './app.config';
|
||||
import { serverRoutes } from './app.routes.server';
|
||||
|
||||
const serverConfig: ApplicationConfig = {
|
||||
providers: [provideServerRendering(withRoutes(serverRoutes))],
|
||||
};
|
||||
|
||||
export const config = mergeApplicationConfig(appConfig, serverConfig);
|
||||
22
apps/shop/src/app/app.config.ts
Normal file
22
apps/shop/src/app/app.config.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
import {
|
||||
ApplicationConfig,
|
||||
provideBrowserGlobalErrorListeners,
|
||||
provideZoneChangeDetection,
|
||||
} from '@angular/core';
|
||||
import { provideRouter } from '@angular/router';
|
||||
import { provideHttpClient, withFetch } from '@angular/common/http';
|
||||
import { appRoutes } from './app.routes';
|
||||
import {
|
||||
provideClientHydration,
|
||||
withEventReplay,
|
||||
} from '@angular/platform-browser';
|
||||
|
||||
export const appConfig: ApplicationConfig = {
|
||||
providers: [
|
||||
provideClientHydration(withEventReplay()),
|
||||
provideBrowserGlobalErrorListeners(),
|
||||
provideZoneChangeDetection({ eventCoalescing: true }),
|
||||
provideRouter(appRoutes),
|
||||
provideHttpClient(withFetch()),
|
||||
],
|
||||
};
|
||||
66
apps/shop/src/app/app.css
Normal file
66
apps/shop/src/app/app.css
Normal file
@@ -0,0 +1,66 @@
|
||||
.app-header {
|
||||
background: #2c3e50;
|
||||
color: white;
|
||||
padding: 1rem 0;
|
||||
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.app-header .container {
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
padding: 0 24px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.app-header h1 {
|
||||
margin: 0;
|
||||
font-size: 1.5rem;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.app-header nav {
|
||||
display: flex;
|
||||
gap: 24px;
|
||||
}
|
||||
|
||||
.app-header nav a {
|
||||
color: white;
|
||||
text-decoration: none;
|
||||
font-size: 1rem;
|
||||
padding: 8px 16px;
|
||||
border-radius: 4px;
|
||||
transition: background 0.3s;
|
||||
}
|
||||
|
||||
.app-header nav a:hover {
|
||||
background: rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
|
||||
.app-header nav a.active {
|
||||
background: #3498db;
|
||||
}
|
||||
|
||||
.app-main {
|
||||
min-height: calc(100vh - 140px);
|
||||
background: #f5f5f5;
|
||||
}
|
||||
|
||||
.app-footer {
|
||||
background: #34495e;
|
||||
color: white;
|
||||
padding: 24px 0;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.app-footer .container {
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
padding: 0 24px;
|
||||
}
|
||||
|
||||
.app-footer p {
|
||||
margin: 8px 0;
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
19
apps/shop/src/app/app.html
Normal file
19
apps/shop/src/app/app.html
Normal file
@@ -0,0 +1,19 @@
|
||||
<header class="app-header">
|
||||
<div class="container">
|
||||
<h1>{{ title }}</h1>
|
||||
<nav>
|
||||
<a routerLink="/products" routerLinkActive="active">Products</a>
|
||||
</nav>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<main class="app-main">
|
||||
<router-outlet></router-outlet>
|
||||
</main>
|
||||
|
||||
<footer class="app-footer">
|
||||
<div class="container">
|
||||
<p>© 2025 Nx Shop Demo - Showcasing Nx Monorepo Features</p>
|
||||
<p>Frontend (Angular) + Backend (Express) + Shared Libraries</p>
|
||||
</div>
|
||||
</footer>
|
||||
12
apps/shop/src/app/app.routes.server.ts
Normal file
12
apps/shop/src/app/app.routes.server.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
import { RenderMode, ServerRoute } from '@angular/ssr';
|
||||
|
||||
export const serverRoutes: ServerRoute[] = [
|
||||
{
|
||||
path: 'products/:id',
|
||||
renderMode: RenderMode.Server,
|
||||
},
|
||||
{
|
||||
path: '**',
|
||||
renderMode: RenderMode.Server,
|
||||
},
|
||||
];
|
||||
25
apps/shop/src/app/app.routes.ts
Normal file
25
apps/shop/src/app/app.routes.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
import { Route } from '@angular/router';
|
||||
|
||||
export const appRoutes: Route[] = [
|
||||
{
|
||||
path: '',
|
||||
redirectTo: 'products',
|
||||
pathMatch: 'full',
|
||||
},
|
||||
{
|
||||
path: 'products',
|
||||
loadChildren: () =>
|
||||
import('@org/shop/feature-products').then(m => m.featureProductsRoutes),
|
||||
},
|
||||
{
|
||||
path: 'products',
|
||||
loadChildren: () =>
|
||||
import('@org/shop/feature-product-detail').then(
|
||||
m => m.featureProductDetailRoutes
|
||||
),
|
||||
},
|
||||
{
|
||||
path: '**',
|
||||
redirectTo: 'products',
|
||||
},
|
||||
];
|
||||
58
apps/shop/src/app/app.spec.ts
Normal file
58
apps/shop/src/app/app.spec.ts
Normal file
@@ -0,0 +1,58 @@
|
||||
import { TestBed, ComponentFixture } from '@angular/core/testing';
|
||||
import { App } from './app';
|
||||
import { appRoutes } from './app.routes';
|
||||
import { provideRouter } from '@angular/router';
|
||||
import { By } from '@angular/platform-browser';
|
||||
|
||||
describe('App', () => {
|
||||
let component: App;
|
||||
let fixture: ComponentFixture<App>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
imports: [App],
|
||||
providers: [provideRouter(appRoutes)],
|
||||
}).compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(App);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create the app component', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should render title in header', () => {
|
||||
const compiled = fixture.nativeElement as HTMLElement;
|
||||
expect(compiled.querySelector('h1')?.textContent).toContain('Nx Shop Demo');
|
||||
});
|
||||
|
||||
it('should render navigation links', () => {
|
||||
const navLinks = fixture.debugElement.queryAll(By.css('nav a'));
|
||||
expect(navLinks.length).toBeGreaterThan(0);
|
||||
expect(navLinks[0].nativeElement.textContent).toContain('Products');
|
||||
expect(navLinks[0].nativeElement.getAttribute('routerLink')).toBe(
|
||||
'/products'
|
||||
);
|
||||
});
|
||||
|
||||
it('should render footer with correct copyright', () => {
|
||||
const footer = fixture.nativeElement.querySelector('.app-footer');
|
||||
expect(footer).toBeTruthy();
|
||||
expect(footer?.textContent).toContain('© 2025 Nx Shop Demo');
|
||||
expect(footer?.textContent).toContain(
|
||||
'Frontend (Angular) + Backend (Express) + Shared Libraries'
|
||||
);
|
||||
});
|
||||
|
||||
it('should have router outlet for dynamic content', () => {
|
||||
const routerOutlet = fixture.nativeElement.querySelector('router-outlet');
|
||||
expect(routerOutlet).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should apply change detection strategy OnPush', () => {
|
||||
const metadata = (App as unknown as { ɵcmp: { onPush: boolean } })['ɵcmp'];
|
||||
expect(metadata.onPush).toBeTruthy();
|
||||
});
|
||||
});
|
||||
13
apps/shop/src/app/app.ts
Normal file
13
apps/shop/src/app/app.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
import { Component, ChangeDetectionStrategy } from '@angular/core';
|
||||
import { RouterModule } from '@angular/router';
|
||||
|
||||
@Component({
|
||||
imports: [RouterModule],
|
||||
selector: 'app-root',
|
||||
templateUrl: './app.html',
|
||||
styleUrl: './app.css',
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class App {
|
||||
protected title = 'Nx Shop Demo';
|
||||
}
|
||||
13
apps/shop/src/index.html
Normal file
13
apps/shop/src/index.html
Normal file
@@ -0,0 +1,13 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<title>shop</title>
|
||||
<base href="/" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<link rel="icon" type="image/x-icon" href="favicon.ico" />
|
||||
</head>
|
||||
<body>
|
||||
<app-root></app-root>
|
||||
</body>
|
||||
</html>
|
||||
7
apps/shop/src/main.server.ts
Normal file
7
apps/shop/src/main.server.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
import { bootstrapApplication, BootstrapContext } from '@angular/platform-browser';
|
||||
import { App } from './app/app';
|
||||
import { config } from './app/app.config.server';
|
||||
|
||||
const bootstrap = (context: BootstrapContext) => bootstrapApplication(App, config, context);
|
||||
|
||||
export default bootstrap;
|
||||
5
apps/shop/src/main.ts
Normal file
5
apps/shop/src/main.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
import { bootstrapApplication } from '@angular/platform-browser';
|
||||
import { appConfig } from './app/app.config';
|
||||
import { App } from './app/app';
|
||||
|
||||
bootstrapApplication(App, appConfig).catch((err) => console.error(err));
|
||||
66
apps/shop/src/server.ts
Normal file
66
apps/shop/src/server.ts
Normal file
@@ -0,0 +1,66 @@
|
||||
import {
|
||||
AngularNodeAppEngine,
|
||||
createNodeRequestHandler,
|
||||
isMainModule,
|
||||
writeResponseToNodeResponse,
|
||||
} from '@angular/ssr/node';
|
||||
import express from 'express';
|
||||
import { dirname, resolve } from 'node:path';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
|
||||
const serverDistFolder = dirname(fileURLToPath(import.meta.url));
|
||||
const browserDistFolder = resolve(serverDistFolder, '../browser');
|
||||
|
||||
const app = express();
|
||||
const angularApp = new AngularNodeAppEngine();
|
||||
|
||||
/**
|
||||
* Example Express Rest API endpoints can be defined here.
|
||||
* Uncomment and define endpoints as necessary.
|
||||
*
|
||||
* Example:
|
||||
* ```ts
|
||||
* app.get('/api/**', (req, res) => {
|
||||
* // Handle API request
|
||||
* });
|
||||
* ```
|
||||
*/
|
||||
|
||||
/**
|
||||
* Serve static files from /browser
|
||||
*/
|
||||
app.use(
|
||||
express.static(browserDistFolder, {
|
||||
maxAge: '1y',
|
||||
index: false,
|
||||
redirect: false,
|
||||
})
|
||||
);
|
||||
|
||||
/**
|
||||
* Handle all other requests by rendering the Angular application.
|
||||
*/
|
||||
app.use('/**', (req, res, next) => {
|
||||
angularApp
|
||||
.handle(req)
|
||||
.then((response) =>
|
||||
response ? writeResponseToNodeResponse(response, res) : next()
|
||||
)
|
||||
.catch(next);
|
||||
});
|
||||
|
||||
/**
|
||||
* Start the server if this module is the main entry point.
|
||||
* The server listens on the port defined by the `PORT` environment variable, or defaults to 4000.
|
||||
*/
|
||||
if (isMainModule(import.meta.url)) {
|
||||
const port = process.env['PORT'] || 4000;
|
||||
app.listen(port, () => {
|
||||
console.log(`Node Express server listening on http://localhost:${port}`);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Request handler used by the Angular CLI (for dev-server and during build) or Firebase Cloud Functions.
|
||||
*/
|
||||
export const reqHandler = createNodeRequestHandler(app);
|
||||
38
apps/shop/src/styles.css
Normal file
38
apps/shop/src/styles.css
Normal file
@@ -0,0 +1,38 @@
|
||||
/* Global Styles */
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen,
|
||||
Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
|
||||
line-height: 1.6;
|
||||
color: #333;
|
||||
background: #f5f5f5;
|
||||
}
|
||||
|
||||
a {
|
||||
color: #3498db;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
button {
|
||||
font-family: inherit;
|
||||
}
|
||||
|
||||
input,
|
||||
select,
|
||||
textarea {
|
||||
font-family: inherit;
|
||||
}
|
||||
|
||||
img {
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
13
apps/shop/src/test-setup.ts
Normal file
13
apps/shop/src/test-setup.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
import '@angular/compiler';
|
||||
import '@analogjs/vitest-angular/setup-zone';
|
||||
|
||||
import {
|
||||
BrowserTestingModule,
|
||||
platformBrowserTesting,
|
||||
} from '@angular/platform-browser/testing';
|
||||
import { getTestBed } from '@angular/core/testing';
|
||||
|
||||
getTestBed().initTestEnvironment(
|
||||
BrowserTestingModule,
|
||||
platformBrowserTesting()
|
||||
);
|
||||
25
apps/shop/tsconfig.app.json
Normal file
25
apps/shop/tsconfig.app.json
Normal file
@@ -0,0 +1,25 @@
|
||||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "../../dist/out-tsc",
|
||||
"types": ["node"]
|
||||
},
|
||||
"include": ["src/**/*.ts"],
|
||||
"exclude": [
|
||||
"jest.config.ts",
|
||||
"src/test-setup.ts",
|
||||
"src/**/*.test.ts",
|
||||
"src/**/*.spec.ts",
|
||||
"vite.config.ts",
|
||||
"vite.config.mts",
|
||||
"vitest.config.ts",
|
||||
"vitest.config.mts",
|
||||
"src/**/*.test.tsx",
|
||||
"src/**/*.spec.tsx",
|
||||
"src/**/*.test.js",
|
||||
"src/**/*.spec.js",
|
||||
"src/**/*.test.jsx",
|
||||
"src/**/*.spec.jsx",
|
||||
"src/test-setup.ts"
|
||||
]
|
||||
}
|
||||
33
apps/shop/tsconfig.json
Normal file
33
apps/shop/tsconfig.json
Normal file
@@ -0,0 +1,33 @@
|
||||
{
|
||||
"extends": "../../tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"strict": true,
|
||||
"noImplicitOverride": true,
|
||||
"noPropertyAccessFromIndexSignature": true,
|
||||
"noImplicitReturns": true,
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"target": "es2022",
|
||||
"moduleResolution": "bundler",
|
||||
"isolatedModules": true,
|
||||
"emitDecoratorMetadata": false,
|
||||
"module": "preserve",
|
||||
"lib": ["dom", "es2022"]
|
||||
},
|
||||
"angularCompilerOptions": {
|
||||
"enableI18nLegacyMessageIdFormat": false,
|
||||
"strictInjectionParameters": true,
|
||||
"strictInputAccessModifiers": true,
|
||||
"typeCheckHostBindings": true,
|
||||
"strictTemplates": true
|
||||
},
|
||||
"files": [],
|
||||
"include": [],
|
||||
"references": [
|
||||
{
|
||||
"path": "./tsconfig.app.json"
|
||||
},
|
||||
{
|
||||
"path": "./tsconfig.spec.json"
|
||||
}
|
||||
]
|
||||
}
|
||||
29
apps/shop/tsconfig.spec.json
Normal file
29
apps/shop/tsconfig.spec.json
Normal file
@@ -0,0 +1,29 @@
|
||||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "../../dist/out-tsc",
|
||||
"types": [
|
||||
"vitest/globals",
|
||||
"vitest/importMeta",
|
||||
"vite/client",
|
||||
"node",
|
||||
"vitest"
|
||||
]
|
||||
},
|
||||
"include": [
|
||||
"vite.config.ts",
|
||||
"vite.config.mts",
|
||||
"vitest.config.ts",
|
||||
"vitest.config.mts",
|
||||
"src/**/*.test.ts",
|
||||
"src/**/*.spec.ts",
|
||||
"src/**/*.test.tsx",
|
||||
"src/**/*.spec.tsx",
|
||||
"src/**/*.test.js",
|
||||
"src/**/*.spec.js",
|
||||
"src/**/*.test.jsx",
|
||||
"src/**/*.spec.jsx",
|
||||
"src/**/*.d.ts"
|
||||
],
|
||||
"files": ["src/test-setup.ts"]
|
||||
}
|
||||
28
apps/shop/vite.config.mts
Normal file
28
apps/shop/vite.config.mts
Normal file
@@ -0,0 +1,28 @@
|
||||
/// <reference types='vitest' />
|
||||
import { defineConfig } from 'vite';
|
||||
import angular from '@analogjs/vite-plugin-angular';
|
||||
import tsconfigPaths from 'vite-tsconfig-paths';
|
||||
import { nxCopyAssetsPlugin } from '@nx/vite/plugins/nx-copy-assets.plugin';
|
||||
|
||||
export default defineConfig(() => ({
|
||||
root: __dirname,
|
||||
cacheDir: '../../node_modules/.vite/apps/shop',
|
||||
plugins: [angular(), tsconfigPaths(), nxCopyAssetsPlugin(['*.md'])],
|
||||
// Uncomment this if you are using workers.
|
||||
// worker: {
|
||||
// plugins: [ nxViteTsPaths() ],
|
||||
// },
|
||||
test: {
|
||||
name: 'shop',
|
||||
watch: false,
|
||||
globals: true,
|
||||
environment: 'jsdom',
|
||||
include: ['{src,tests}/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
||||
setupFiles: ['src/test-setup.ts'],
|
||||
reporters: ['default'],
|
||||
coverage: {
|
||||
reportsDirectory: '../../coverage/apps/shop',
|
||||
provider: 'v8' as const,
|
||||
},
|
||||
},
|
||||
}));
|
||||
Reference in New Issue
Block a user