Skip to content

Commit

Permalink
Fix macOS frontend CI disconnecting issue (#2968)
Browse files Browse the repository at this point in the history
This PR includes a few efforts to improve frontend CI on macOS.

1. Changed macOS CI to run on arm64 arch instead of x64. The is the main
cause of disconnecting issue.
2. Upgraded testing-related packages to the latest: 
- karma to 6.4.4 (applied a custom fix for Chrome > 128.0.0.0.0 on macOS
arm64, see my post
angular/angular-cli#28271 (comment))
    - jasmine-core to 5.4.0
3. Fixed many problematic test cases, including:
    - Empty test cases (no `it` cases).
- Wrong dependency injection (especially on HttpClient should use
`HttpClientTestingModule`).
    - Wrong global NzMessageModule import.
  • Loading branch information
Yicong-Huang authored and PurelyBlank committed Dec 4, 2024
1 parent 1c6d095 commit 70334ae
Show file tree
Hide file tree
Showing 20 changed files with 133 additions and 285 deletions.
23 changes: 12 additions & 11 deletions .github/workflows/github-action-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,30 +17,31 @@ jobs:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os:
- ubuntu-latest
- macos-latest
- windows-latest
os: [ubuntu-latest, windows-latest, macos-latest]
include:
- os: macos-latest
arch: arm64
- os: ubuntu-latest
arch: x64
- os: windows-latest
arch: x64
node-version:
- 18
architecture:
- x64
steps:
- name: Checkout Texera
uses: actions/checkout@v2
- name: Setup node
uses: actions/setup-node@v2
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
architecture: ${{ matrix.architecture }}
architecture: ${{ matrix.arch }}
- uses: actions/cache@v2
with:
path: |
core/gui/node_modules
core/gui/multi-target/node_modules
key: ${{ runner.os }}-yarn-cache-v6-${{ hashFiles('**/yarn.lock') }}
key: ${{ runner.os }}-${{ matrix.arch }}-${{ matrix.node-version }}-yarn-cache-v1-${{ hashFiles('**/yarn.lock') }}
restore-keys: |
${{ runner.os }}-yarn-cache-v6-
${{ runner.os }}-${{ matrix.arch }}-${{ matrix.node-version }}-yarn-cache-v1-
- name: Prepare Yarn 4.5.1
run: corepack enable && corepack prepare [email protected] --activate && yarn --cwd core/gui set version 4.5.1
- name: Install dependency
Expand Down
61 changes: 33 additions & 28 deletions core/gui/karma.conf.js
Original file line number Diff line number Diff line change
@@ -1,46 +1,51 @@
// Karma configuration file, see link for more information
// https://karma-runner.github.io/1.0/config/configuration-file.html

module.exports = function(config) {
// Karma configuration file
module.exports = function (config) {
config.set({
basePath: "",
frameworks: ['waitwebpack', "jasmine", "@angular-devkit/build-angular"],
frameworks: ["jasmine", "@angular-devkit/build-angular"],
plugins: [
require("karma-jasmine"),
require("karma-chrome-launcher"),
require("karma-coverage"),
require("karma-jasmine-html-reporter"),
require('./karma.waitwebpack'),
require("@angular-devkit/build-angular/plugins/karma")
],
client: {
clearContext: false, // leave Jasmine Spec Runner output visible in browser
clearContext: config.singleRun, // Leave Jasmine Spec Runner output visible in the browser
jasmine: {
random: false // disable the random running order
}
random: false, // Disable random order for consistent test results
},
},
customLaunchers: {
ChromeHeadlessCustom: {
base: 'ChromeHeadless',
base: "ChromeHeadless",
flags: [
'--no-sandbox',
'--headless',
'--disable-gpu',
'--disable-translate',
'--disable-extensions'
"--no-sandbox",
"--headless=new",
"--remote-debugging-port=9222", // Enable remote debugging for better error output
"--disable-gpu",
"--disable-translate",
"--disable-extensions",
"--disable-dev-shm-usage", // Avoid /dev/shm issues in CI environments
"--disable-extensions",
"--disable-background-networking",
"--disable-background-timer-throttling",
"--disable-backgrounding-occluded-windows",
"--disable-breakpad",
"--disable-sync",
],
},
},
reporters: ["progress", "kjhtml"],
port: 9876,
colors: true,
logLevel: config.LOG_INFO,
autoWatch: true,
browsers: ["ChromeHeadlessCustom"],
singleRun: false,
captureTimeout: 240000,
browserDisconnectTimeout: 60000,
browserDisconnectTolerance: 1,
browserNoActivityTimeout: 240000
reporters: ["dots"], // Use dots reporter
port: 9876, // Karma's web server port
colors: true, // Enable colors in the output (reporters and logs)
logLevel: config.LOG_INFO, // Set log level
autoWatch: false, // Disable auto-watch to prevent re-runs in CI
concurrency: 1, // Launch only one browser at a time
browsers: ["ChromeHeadlessCustom"], // Run tests in headless Chrome
singleRun: true, // Ensure Karma exits after running tests once (useful for CI)
restartOnFileChange: false, // Disable file change restarts in CI
captureTimeout: 30000, // 30-second timeout for capturing the browser
browserDisconnectTimeout: 60000, // 60-second disconnect timeout
browserDisconnectTolerance: 1, // Allow up to 1 disconnect before failing
browserNoActivityTimeout: 60000, // 60-second no-activity timeout
});
};
27 changes: 0 additions & 27 deletions core/gui/karma.waitwebpack.js

This file was deleted.

18 changes: 8 additions & 10 deletions core/gui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@
"build": "ng build --configuration=production --progress=false --source-map=false",
"build:ci": "nx build --configuration=production --progress=false --source-map=false",
"analyze": "ng build --configuration=production --stats-json && webpack-bundle-analyzer dist/stats.json",
"test": "ng test",
"test:ci": "node --max_old_space_size=6144 ./node_modules/nx/bin/nx test --watch=false --progress=false --browsers=ChromeHeadless",
"test": "ng test --watch=false",
"test:ci": "node --max-old-space-size=6144 ./node_modules/nx/bin/nx test --watch=false --progress=false",
"prettier:fix": "prettier --write ./src",
"lint": "ng lint",
"eslint:fix": "yarn eslint --fix ./src",
Expand Down Expand Up @@ -112,7 +112,7 @@
"@types/dagre": "0.7.47",
"@types/file-saver": "2.0.5",
"@types/graphlib": "2.1.8",
"@types/jasmine": "3.10.3",
"@types/jasmine": "4.6.4",
"@types/json-schema": "7.0.9",
"@types/lodash": "4.14.179",
"@types/node": "18.15.5",
Expand All @@ -133,13 +133,11 @@
"eslint-plugin-rxjs-angular": "2.0.1",
"fs-extra": "10.0.1",
"git-describe": "4.1.0",
"jasmine-core": "3.8.0",
"jasmine-spec-reporter": "5.0.2",
"karma": "6.4.3",
"karma-chrome-launcher": "3.1.0",
"karma-coverage": "2.2.1",
"karma-jasmine": "4.0.1",
"karma-jasmine-html-reporter": "1.7.0",
"jasmine-core": "5.4.0",
"jasmine-spec-reporter": "7.0.0",
"karma": "6.4.4",
"karma-chrome-launcher": "3.2.0",
"karma-jasmine": "5.1.0",
"nodecat": "2.0.0",
"nx": "20.0.3",
"nz-tslint-rules": "0.901.2",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { ComponentFixture, TestBed } from "@angular/core/testing";

import { FiltersInstructionsComponent } from "./filters-instructions.component";
import { NzPopoverModule } from "ng-zorro-antd/popover";

describe("FiltersInstructionsComponent", () => {
let component: FiltersInstructionsComponent;
Expand All @@ -9,6 +10,7 @@ describe("FiltersInstructionsComponent", () => {
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [FiltersInstructionsComponent],
imports: [NzPopoverModule],
}).compileComponents();
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,10 @@ import { OperatorMetadataService } from "src/app/workspace/service/operator-meta
import { WorkflowPersistService } from "src/app/common/service/workflow-persist/workflow-persist.service";
import { StubWorkflowPersistService } from "src/app/common/service/workflow-persist/stub-workflow-persist.service";
import { testWorkflowEntries } from "../../user-dashboard-test-fixtures";
import { HttpClient, HttpHandler } from "@angular/common/http";
import { NzDropDownModule } from "ng-zorro-antd/dropdown";
import { JwtHelperService, JWT_OPTIONS } from "@auth0/angular-jwt";
import { JWT_OPTIONS, JwtHelperService } from "@auth0/angular-jwt";
import { FormsModule } from "@angular/forms";
import { HttpClientTestingModule } from "@angular/common/http/testing";

describe("FiltersComponent", () => {
let component: FiltersComponent;
Expand All @@ -18,14 +19,12 @@ describe("FiltersComponent", () => {
await TestBed.configureTestingModule({
declarations: [FiltersComponent],
providers: [
HttpClient,
HttpHandler,
JwtHelperService,
{ provide: JWT_OPTIONS, useValue: {} },
{ provide: WorkflowPersistService, useValue: new StubWorkflowPersistService(testWorkflowEntries) },
{ provide: OperatorMetadataService, useClass: StubOperatorMetadataService },
],
imports: [NzDropDownModule],
imports: [NzDropDownModule, FormsModule, HttpClientTestingModule],
}).compileComponents();
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,29 +10,23 @@ describe("ListItemComponent", () => {
let component: ListItemComponent;
let fixture: ComponentFixture<ListItemComponent>;
let workflowPersistService: jasmine.SpyObj<WorkflowPersistService>;
let nzModalService: jasmine.SpyObj<NzModalService>;

beforeEach(async () => {
const workflowPersistServiceSpy = jasmine.createSpyObj("WorkflowPersistService", [
"updateWorkflowName",
"updateWorkflowDescription",
]);
const nzModalServiceSpy = jasmine.createSpyObj("NzModalService", ["create"]);

await TestBed.configureTestingModule({
imports: [HttpClientTestingModule],
declarations: [ListItemComponent],
providers: [
{ provide: WorkflowPersistService, useValue: workflowPersistServiceSpy },
{ provide: NzModalService, useValue: nzModalServiceSpy },
],
providers: [{ provide: WorkflowPersistService, useValue: workflowPersistServiceSpy }, NzModalService],
schemas: [NO_ERRORS_SCHEMA],
}).compileComponents();

fixture = TestBed.createComponent(ListItemComponent);
component = fixture.componentInstance;
workflowPersistService = TestBed.inject(WorkflowPersistService) as jasmine.SpyObj<WorkflowPersistService>;
nzModalService = TestBed.inject(NzModalService) as jasmine.SpyObj<NzModalService>;
});

it("should update workflow name successfully", () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { ComponentFixture, TestBed } from "@angular/core/testing";
import { HttpClientModule } from "@angular/common/http";
import { UserAvatarComponent } from "./user-avatar.component";
import { HttpClientTestingModule } from "@angular/common/http/testing";
import { NzAvatarModule } from "ng-zorro-antd/avatar";

describe("UserAvatarComponent", () => {
let component: UserAvatarComponent;
Expand All @@ -10,7 +11,7 @@ describe("UserAvatarComponent", () => {
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [UserAvatarComponent],
imports: [HttpClientModule, HttpClientTestingModule],
imports: [HttpClientModule, HttpClientTestingModule, NzAvatarModule],
}).compileComponents();
});

Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
import { ComponentFixture, TestBed } from "@angular/core/testing";
import { UserProjectListItemComponent } from "./user-project-list-item.component";
import { HttpClient, HttpHandler } from "@angular/common/http";
import { NotificationService } from "src/app/common/service/notification/notification.service";
import { UserProjectService } from "../../../../service/user/project/user-project.service";
import { DashboardProject } from "../../../../type/dashboard-project.interface";
import { HttpClientTestingModule } from "@angular/common/http/testing";
import { NzModalService } from "ng-zorro-antd/modal";
import { StubUserService } from "../../../../../common/service/user/stub-user.service";
import { UserService } from "../../../../../common/service/user/user.service";
import { HighlightSearchTermsPipe } from "../../user-workflow/user-workflow-list-item/highlight-search-terms.pipe";

describe("UserProjectListItemComponent", () => {
let component: UserProjectListItemComponent;
Expand All @@ -21,8 +25,14 @@ describe("UserProjectListItemComponent", () => {

beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [UserProjectListItemComponent],
providers: [HttpClient, HttpHandler, NotificationService, UserProjectService],
declarations: [UserProjectListItemComponent, HighlightSearchTermsPipe],
providers: [
NotificationService,
UserProjectService,
NzModalService,
{ provide: UserService, useClass: StubUserService },
],
imports: [HttpClientTestingModule],
}).compileComponents();
});

Expand All @@ -33,4 +43,8 @@ describe("UserProjectListItemComponent", () => {
component.editable = true;
fixture.detectChanges();
});

it("should create", () => {
expect(component).toBeTruthy();
});
});
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
import { ComponentFixture, TestBed } from "@angular/core/testing";
import { UserQuotaComponent } from "./user-quota.component";
import { UserQuotaService } from "../../../service/user/quota/user-quota.service";
import { HttpClientTestingModule } from "@angular/common/http/testing";

describe("UserQuotaComponent", () => {
let component: UserQuotaComponent;
let fixture: ComponentFixture<UserQuotaComponent>;
let userQuotaService: jasmine.SpyObj<UserQuotaService>;
let mockUserQuotaService: jasmine.SpyObj<UserQuotaService>;

beforeEach(() => {
const userQuotaServiceSpy = jasmine.createSpyObj("UserQuotaService", [
mockUserQuotaService = jasmine.createSpyObj("UserQuotaService", [
"getUploadedFiles",
"getCreatedDatasets",
"getCreatedWorkflows",
Expand All @@ -19,11 +20,15 @@ describe("UserQuotaComponent", () => {

TestBed.configureTestingModule({
declarations: [UserQuotaComponent],
providers: [{ provide: UserQuotaService, useValue: userQuotaServiceSpy }],
providers: [{ provide: UserQuotaService, useValue: mockUserQuotaService }],
imports: [HttpClientTestingModule],
});

fixture = TestBed.createComponent(UserQuotaComponent);
component = fixture.componentInstance;
userQuotaService = TestBed.inject(UserQuotaService) as jasmine.SpyObj<UserQuotaService>;
});

it("should create", () => {
expect(component).toBeTruthy();
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -5,26 +5,25 @@ import { testWorkflowEntries } from "../../../user-dashboard-test-fixtures";
import { By } from "@angular/platform-browser";
import { StubWorkflowPersistService } from "../../../../../common/service/workflow-persist/stub-workflow-persist.service";
import { WorkflowPersistService } from "../../../../../common/service/workflow-persist/workflow-persist.service";
import { HttpClient, HttpHandler } from "@angular/common/http";
import { UserProjectService } from "../../../../service/user/project/user-project.service";
import { StubUserProjectService } from "../../../../service/user/project/stub-user-project.service";
import { NzModalModule } from "ng-zorro-antd/modal";
import { HttpClientTestingModule } from "@angular/common/http/testing";
import { HighlightSearchTermsPipe } from "./highlight-search-terms.pipe";
import { NzToolTipModule } from "ng-zorro-antd/tooltip";

describe("UserWorkflowListItemComponent", () => {
let component: UserWorkflowListItemComponent;
let fixture: ComponentFixture<UserWorkflowListItemComponent>;
const fileSaverServiceSpy = jasmine.createSpyObj<FileSaverService>(["saveAs"]);
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [NzModalModule],
imports: [NzModalModule, HttpClientTestingModule, NzToolTipModule],
declarations: [UserWorkflowListItemComponent, HighlightSearchTermsPipe],
providers: [
{ provide: WorkflowPersistService, useValue: new StubWorkflowPersistService(testWorkflowEntries) },
{ provide: UserProjectService, useValue: new StubUserProjectService() },
{ provide: FileSaverService, useValue: fileSaverServiceSpy },
HttpClient,
HttpHandler,
],
}).compileComponents();
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ describe("CodeDebuggerComponent", () => {
afterEach(() => {
// Clean up streams to prevent memory leaks
statusUpdateStream.complete();
component.monacoEditor.dispose();
});

it("should create the component", () => {
Expand Down
Empty file.
Loading

0 comments on commit 70334ae

Please sign in to comment.