Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[#60911] Rehabilitate frontend component test suite #17694

Draft
wants to merge 23 commits into
base: dev
Choose a base branch
from

Conversation

myabc
Copy link
Contributor

@myabc myabc commented Jan 22, 2025

⚠️ This PR also upgrades TypeScript to 5.5, which enables us to take advantage of improvements to the type checker, as well as RegEx syntax checking. If necessary, this work could be broken out into a separate PR.

Ticket

https://community.openproject.org/wp/60911 (part of Feature https://community.openproject.org/wp/60910)

What are you trying to accomplish?

Goals:

  • Get the current frontend test suite running green once again.
  • CI: Create an initial GitHub workflow for the frontend test suite.

This is an alternative to #17677, which removes the frontend test suite entirely.

Screenshots

Test suite results with code coverage

What approach did you choose and why?

This Pull Request initially started out as a spike - to see how easy it would be to restore CI runs for the suite (i.e. setting up a GitHub workflow action). However, once #17648 and #17646 were merged, only ~10 specs out of 450 were failing. As such, I went ahead and have attempted to fix these failures.

GitHub workflow for frontend component test suite

This is as a very simple, "vanilla" workflow action. It relies on the included software in GitHub's Ubuntu 24.04 runner image + setup-node@v4 action to setup the environment and execute the spec suite.

The most significant bit of work was to port the Rake openproject:plugins:register_frontend task to a node script. This was done so that we don't need a step that sets up ruby, installs OpenProject dependencies.

Things to note:

  • The port does not implement generate_plugin_sass, as AFAICT global styling isn't necessary for the frontend test suite to run successfully.
  • For now this hardcodes the list of plugins that we test - I am not terribly familiar with how we're doing plugin management atm, so not sure if this is problematic?.

Spec fixes

The failures in the frontend test suite are a result of the test suite having become out-of-sync with the actual implementation - which is understandable since it hasn't been running on CI for a number of years, and therefore overlooked.

The reasons for the failures and how I fixed them can basically be summarised as follows:

  1. stub data that was out-of-sync with the implementation/didn't confirm to TS interfaces: updated stubs, added explicit types where possible.
  2. CSS selector changes due to component template changes: updated CSS selectors.
  3. CSS selector changes due to upgrading Formly from 5.0 to 6.0 (see https://formly.dev/docs/guide/migration): updated CSS selectors. This PR also replaces the deprecated use of FormlyTemplateOptions with FormlyFieldProps - however there is some additional work that needs to be done to properly deal with Formly 6.x deprecations. I have broken this out into separate work package, op#60912.
  4. an issue with CKEditorSetupService#load() use of dynamic ESM imports: I spent a fair amount of time playing around with angular.json/karma.config.js settings, even going as far as debugging the Webpack config that ng test generates under-the-hood. However I struggled to get past "chunk load errors", so ended up replacing replacing CKEditorSetupService#create() with a spy that returns a stub ICKEditor implementation. I think this is probably a better solution going forward.

To make things easier for review - I have referenced the commits that most likely caused the spec failures in several of this PR's commit messages. I'll also list the related PRs in the checklist below - it would be really fantastic if you could have a quick look at the associated spec changes.

Merge checklist

Additional tasks (might be out-of-scope)

  • Support testing additional browsers (Firefox) (?)
  • Decide if we want to skip long-running "Test suite" (test-core.yml) workflow if frontend test suite check fails*

* I believe this is possible with workflow_run, but @crohr / @machisuji probably know more? If it is technically possible, we should also figure out if introducing workflow dependencies makes sense (as part of op#60910), especially given that the frontend test suite does not currently test any non-Angular TS/JS code.

@myabc myabc force-pushed the feature/github-workflow-test-frontend-unit branch 7 times, most recently from 680e580 to 84318d5 Compare January 24, 2025 23:20
@myabc myabc force-pushed the feature/github-workflow-test-frontend-unit branch 2 times, most recently from 8fc66c7 to e91d371 Compare January 25, 2025 00:07
myabc added 12 commits January 25, 2025 14:17
As of 5a2a501 we are now importing the actual I18n implementation.
Also resolves the following warning:

    Unable to determine file type from the file extension, defaulting to js.
Allows us to perform plugin symlinking and file generation necessary for
bootstapping frontend tests. Based on a standard plugin setup.
Broken with upgrade from v5 to v6. Formly now defines an extra
`formly-field` for a given `formly-form` component.

See: https://formly.dev/docs/guide/migration#10-formly-root-field
Updates spec for store changes made in 077112d and template changes in
9fbb746.
Fixes additional schema warnings.
Updates spec for selector change in 077112d.
Updates spec for store, selector changes in 077112d.

Also forces change detection via `ChangeDetectorRef`.
@myabc myabc force-pushed the feature/github-workflow-test-frontend-unit branch from e91d371 to 4d8bccc Compare January 25, 2025 17:17
Comment on lines +10 to +12
- '**/frontend/**/*.ts'
- '**/frontend/**/*.js'
- '**/frontend/**/*.json'
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be great if someone could check these filter patterns. I was caught out at first by GH Actions lack of support for extended globbing (see [Filter pattern cheat sheet).

@myabc myabc changed the title Feature/GitHub workflow test frontend unit [#60911] Rehabilitate frontend component test suite Jan 25, 2025

- uses: actions/setup-node@v4
with:
node-version: '18.13'
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I specified 18.13 because it's the same version we're using in eslint-core.yml. However we should probably switch both to 20.9.0, the node version specified in docker/ci/Dockerfile, as well as the root package.json in the repo.

jobs:
units:
name: Units
runs-on: ubuntu-latest
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ubuntu-latest resolves to GitHub's Ubuntu 24.04 runner image, which includes Chrome, chromedriver amongst other browsers and drivers.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It might be better to explicitly specify ubuntu-24.04:
image

steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I copied and pasted this from eslint-core.yml, but I think this isn't what we want - according to the docs this fetches all history for all tags and branches. / cc @machisuji


- name: Test (Angular)
id: npm-test
run: npm test -- --code-coverage
Copy link
Contributor Author

@myabc myabc Jan 25, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Although test coverage results are written to stdout (so visible in the job output), we should probably find a way to append the report to the PR somehow - @machisuji @cbliard @crohr any ideas what our options might be?

'node_modules/jquery/dist/jquery.js',
// 'node_modules/angular-mocks/angular-mocks.js'
],
frameworks: ['jasmine', '@angular-devkit/build-angular'],
plugins: [
require('karma-jasmine'),
require('karma-chrome-launcher'),
require('karma-coverage'),
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From glancing at the source for @angular-devkit/build-webpack, ng test should append this plugin automatically if "test"/"options"/"codeCoverage": true is specified. However I couldn't get it to work.

// This is a very project resource specific hack to allow macros on description and statusExplanation but
// disable it for custom fields. As the formly based approach is currently limited to projects, and that is to be removed,
// such a "pragmatic" approach should be ok.
macros: (this.templateOptions.property as string).startsWith('customField') ? 'none' : 'resource',
options: { rtl: this.templateOptions?.rtl },
macros: this.templateOptions.property?.startsWith('customField') ? 'none' : 'resource',
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

safe navigation operator is necessary here!

Comment on lines +30 to +46
payloadValue?:{ href?:string|null };
rtl?:boolean;
locale?:string;
bindLabel?:string;
bindValue?:string;
searchable?:boolean;
editorType?:ICKEditorType;
noWrapLabel?:boolean;
virtualScroll?:boolean;
clearOnBackspace?:boolean;
clearSearchOnAdd?:boolean;
hideSelected?:boolean;
text?:Record<string, string>;
typeahead?:boolean;
inlineLabel?:boolean;
clearable?:boolean;
multiple?:boolean;
Copy link
Contributor Author

@myabc myabc Jan 25, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FormlyFieldConfig is now a generic interface with a Props type parameter. As stated in the associated commit, this could (and perhaps should) be reworked as a an interface hierarchy (+ discriminated unions), defining only the applicable properties for a given OPInputType or template type. Could possibly be done as part of op#60912.

changeDetectorRef = fixture.debugElement.injector.get(ChangeDetectorRef) as jasmine.SpyObj<ChangeDetectorRef>;
// @ts-ignore
component.workPackage = { id: 'testId' };

changeDetectorRef.markForCheck();
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

manually invoking change detection gets this spec passing - not sure if this is the canonical way of testing asynchronous in Angular tests though?

@@ -41,8 +41,8 @@ export class GitActionsService {
return str
.replace(/&/g, 'and ') // & becomes and
.replace(/ +/g, '-') // Spaces become dashes
.replace(/[\000-\039]/g, '') // ASCII control characters are out
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

\039 isn't a valid Octal - cool TS 5.5 validates regexen!

@@ -4,6 +4,7 @@ import {
import { DOCUMENT } from '@angular/common';
import { DomAutoscrollService } from 'core-app/shared/helpers/drag-and-drop/dom-autoscroll.service';
import { findIndex, reinsert } from 'core-app/shared/helpers/drag-and-drop/drag-and-drop.helpers';
import dragula from 'dragula';
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Need to double-check this - Dragula is required with the expose-loader in init-vendors.ts, which we're not currently importing in test.ts. We are also not importing typings/shims.d.ts.

myabc added 11 commits January 25, 2025 18:01
Add stubs for ICKEditor: this works around an issue with the use of
dynamic ESM imports in `CKEditorSetupService#load()` not working with
our Karma/Webpack configuration.
Replaces deprecated `FormlyTemplateOptions` interface.
See: https://formly.dev/docs/guide/migration#ngx-formlycorejson-schema

N.B. That further improvements to type safety could be made by extending
`IOPFormlyTemplateOptions`, employing discriminating unions.
Relate to Angular router:

    NG0303: Can't bind to 'uiSref' since it isn't a known property of 'a' (used in the 'ScrollableTabsComponent' component template).
    NG0303: Can't bind to 'uiParams' since it isn't a known property of 'a' (used in the 'ScrollableTabsComponent' component template).
Match the `node-version` defined in root `package.json` `engines` entry,
`.github/workflows/docker.yml` and `docker/ci/Dockerfile`.
@myabc myabc force-pushed the feature/github-workflow-test-frontend-unit branch from 4d8bccc to 148c151 Compare January 25, 2025 21:03
@myabc myabc requested a review from machisuji January 25, 2025 21:03
@oliverguenther
Copy link
Member

oliverguenther commented Jan 26, 2025

@myabc Feature tests are broken due to

Error: Failed to initialize Angular compilation - The Angular Compiler requires TypeScript >=5.2.0 and <5.5.0 but 5.5.4 was found instead.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

2 participants