Browse Source

Update node. (#1286)

* Update node.

* Dummy update

* Fix some tests.

* Cleanup

* Update test.

* Source folder.
pull/1288/head
Sebastian Stehle 5 months ago
committed by GitHub
parent
commit
eec552df41
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 4
      Dockerfile
  2. 2
      README.md
  3. 2
      dev/frontend-build/Dockerfile
  4. 7
      frontend/angular.json
  5. 2
      frontend/eslint.config.js
  6. 606
      frontend/package-lock.json
  7. 4
      frontend/package.json
  8. 18
      frontend/src/app/framework/angular/forms/focus-on-init.directive.spec.ts
  9. 8
      frontend/src/app/framework/angular/forms/focus-on-init.directive.ts
  10. 28
      frontend/src/app/framework/services/loading.service.spec.ts
  11. 8
      frontend/src/app/framework/services/loading.service.ts
  12. 18
      frontend/src/test-setup.ts
  13. 7
      frontend/vitest.config.js

4
Dockerfile

@ -13,7 +13,7 @@ ARG SQUIDEX__BUILD__ARGS
RUN echo "ARGS IS $SQUIDEX__BUILD__ARGS"
WORKDIR /build
WORKDIR /source
# Copy nuget project files.
COPY backend/Directory.Build.props ./
@ -57,7 +57,7 @@ RUN dotnet tool install --tool-path /tools dotnet-dump \
#
FROM squidex/frontend-build:22.19 AS frontend
WORKDIR /build
WORKDIR /source
ENV CONTINUOUS_INTEGRATION=1

2
README.md

@ -1,6 +1,6 @@
![Squidex Logo](https://raw.githubusercontent.com/Squidex/squidex/master/media/logo-wide.png "Squidex")
# What is Squidex?
# What is Squidex??
Squidex is an open source headless CMS and content management hub. In contrast to a traditional CMS Squidex provides a rich API with OData filter and Swagger definitions. It is up to you to build your UI on top of it. It can be website, a native app or just another server. We build it with ASP.NET Core and CQRS and is tested for Windows and Linux on modern browsers.

2
dev/frontend-build/Dockerfile

@ -1,4 +1,4 @@
FROM node:22.19.0-slim
FROM node:24.13.0-slim
ENV CHROME_BIN=/usr/bin/chromium

7
frontend/angular.json

@ -170,7 +170,12 @@
"defaultConfiguration": "development"
},
"test": {
"builder": "@angular/build:unit-test"
"builder": "@angular/build:unit-test",
"options": {
"tsConfig": "./tsconfig.spec.json",
"runnerConfig": "vitest.config.js",
"setupFiles": ["./src/test-setup.ts"]
}
},
"storybook": {
"builder": "@storybook/angular:start-storybook",

2
frontend/eslint.config.js

@ -4,7 +4,6 @@ const {
const globals = require("globals");
const tsParser = require("@typescript-eslint/parser");
const deprecation = require("eslint-plugin-deprecation");
const importPlugin = require("eslint-plugin-import");
const typescriptEslint = require("@typescript-eslint/eslint-plugin");
@ -42,7 +41,6 @@ module.exports = defineConfig([{
),
plugins: {
deprecation,
import: importPlugin,
"@typescript-eslint": typescriptEslint,
},

606
frontend/package-lock.json

File diff suppressed because it is too large

4
frontend/package.json

@ -98,8 +98,6 @@
"@typescript-eslint/parser": "^8.54.0",
"copy-webpack-plugin": "^13.0.1",
"eslint": "^9.39.2",
"eslint-config-airbnb-typescript": "18.0.0",
"eslint-plugin-deprecation": "^3.0.0",
"eslint-plugin-import": "2.32.0",
"eslint-plugin-jsx-a11y": "6.10.2",
"eslint-plugin-storybook": "^10.2.7",
@ -113,7 +111,7 @@
"stylelint-scss": "7.0.0",
"typescript": "5.9.3",
"vite-tsconfig-paths": "^6.0.5",
"vitest": "^4.0.18"
"vitest": "^4.0.8"
},
"overrides": {
"ng2-charts": {

18
frontend/src/app/framework/angular/forms/focus-on-init.directive.spec.ts

@ -30,27 +30,21 @@ describe('FocusOnInitDirective', () => {
it('should call focus on element if init', async () => {
const directive = new FocusOnInitDirective(element);
directive.scheduler = action => action();
directive.select = false;
directive.ngAfterViewInit();
setTimeout(() => {
expect(isFocusCalled).toBeTruthy();
expect(isSelectCalled).toBeFalsy();
}, 200);
expect(isFocusCalled).toBeTruthy();
expect(isSelectCalled).toBeFalsy();
});
it('should call select on element if init', async () => {
const directive = new FocusOnInitDirective(element);
directive.scheduler = action => action();
directive.select = true;
directive.ngAfterViewInit();
setTimeout(() => {
expect(isFocusCalled).toBeTruthy();
expect(isSelectCalled).toBeTruthy();
}, 200);
expect(isFocusCalled).toBeTruthy();
expect(isSelectCalled).toBeTruthy();
});
});

8
frontend/src/app/framework/angular/forms/focus-on-init.directive.ts

@ -18,6 +18,10 @@ export class FocusOnInitDirective implements AfterViewInit {
@Input({ alias: 'sqxFocusOnInit', transform: booleanAttribute })
public enabled = true;
public scheduler: ((action: (() => void)) => void) = action => {
setTimeout(action, 200);
};
constructor(
private readonly element: ElementRef<HTMLElement>,
) {
@ -28,7 +32,7 @@ export class FocusOnInitDirective implements AfterViewInit {
return;
}
setTimeout(() => {
this.scheduler(() => {
if (Types.isFunction(this.element.nativeElement.focus)) {
this.element.nativeElement.focus();
}
@ -40,6 +44,6 @@ export class FocusOnInitDirective implements AfterViewInit {
input.select();
}
}
}, 100);
});
}
}

28
frontend/src/app/framework/services/loading.service.spec.ts

@ -22,9 +22,9 @@ describe('LoadingService', () => {
it('should set to loaded', () => {
const loadingService = new LoadingService(<any>{ events });
loadingService.scheduler = action => action();
let state = false;
loadingService.loading.subscribe(v => {
state = v;
});
@ -35,9 +35,9 @@ describe('LoadingService', () => {
it('should set to loaded on navigation start', () => {
const loadingService = new LoadingService(<any>{ events });
loadingService.scheduler = action => action();
let state = false;
loadingService.loading.subscribe(v => {
state = v;
});
@ -51,7 +51,6 @@ describe('LoadingService', () => {
const loadingService = new LoadingService(<any>{ events });
let state = false;
loadingService.loading.subscribe(v => {
state = v;
});
@ -63,42 +62,35 @@ describe('LoadingService', () => {
it('should not unset from loaded delayed', async () => {
const loadingService = new LoadingService(<any>{ events });
loadingService.scheduler = action => action();
let state = false;
loadingService.loading.subscribe(v => {
state = v;
});
loadingService.startLoading('1');
loadingService.completeLoading('1');
setTimeout(() => {
expect(state).toBeFalsy();
}, 400);
expect(state).toBeFalsy();
});
it('should not unset from loaded delayed on navigation event', async () => {
const loadingService = new LoadingService(<any>{ events });
loadingService.scheduler = action => action();
let state = false;
loadingService.loading.subscribe(v => {
state = v;
});
events.next(new NavigationStart(0, ''));
events.next(new NavigationError(0, '', 0));
setTimeout(() => {
expect(state).toBeFalsy();
}, 400);
expect(state).toBeFalsy();
});
it('should set back to loaded after several completions', async () => {
const loadingService = new LoadingService(<any>{ events });
loadingService.scheduler = action => action();
let state = false;
@ -110,10 +102,6 @@ describe('LoadingService', () => {
loadingService.completeLoading('1');
loadingService.startLoading('2');
setTimeout(() => {
expect(state).toBeTruthy();
}, 400);
expect(state).toBeTruthy();
});
});

8
frontend/src/app/framework/services/loading.service.ts

@ -22,6 +22,10 @@ export class LoadingService implements OnDestroy {
return this.loading$.pipe(map(x => x > 0));
}
public scheduler: ((action: (() => void)) => void) = action => {
setTimeout(action, 200);
};
constructor(router: Router) {
this.routerSubscription =
router.events.subscribe(event => {
@ -54,13 +58,13 @@ export class LoadingService implements OnDestroy {
if (this.loadingOperations[key]) {
delete this.loadingOperations[key];
setTimeout(() => {
this.scheduler(() => {
const value = this.loading$.value;
if (value > 0) {
this.loading$.next(value - 1);
}
}, 250);
});
}
}
}

18
frontend/src/test-setup.ts

@ -0,0 +1,18 @@
import { getTestBed, TestBed } from "@angular/core/testing";
import { BrowserTestingModule, platformBrowserTesting } from "@angular/platform-browser/testing";
import { afterEach } from "vitest";
afterEach(() => {
TestBed.resetTestingModule();
});
// Only initialize test environment if it hasn't been initialized yet
// This prevents errors when vitest runs tests in parallel (e.g., in CI)
try {
getTestBed().initTestEnvironment(
BrowserTestingModule,
platformBrowserTesting(),
);
} catch {
// Test environment already initialized, ignore the error
}

7
frontend/vitest.config.js

@ -0,0 +1,7 @@
import { defineConfig } from "vitest/config";
export default defineConfig({
test: {
passWithNoTests: true,
},
});
Loading…
Cancel
Save