Skip to content

Commit

Permalink
INT-3298: Updated tests to BDD style (#390)
Browse files Browse the repository at this point in the history
* INT-3298: Added TestHooks.ts

* INT-3298: Added TestHelpers.ts

* INT-3298: support for using minitature to specify tinymce version

* INT-3298: Migrated LoadTinyTest to BDD style

* INT-3298: throwTimeout message param is now optional

* INT-3298: Migrated NgZoneTest.ts to BDD style

* INT-3298: Initial migration changes to NgModelTest.ts

* INT-3298: Added a *Test.ts eslint override

* INT-3298: Refactored EditorFixture to extend ComponentFixture

* INT-3298: Increased skin load timeout

* INT-3298: loadedEditor$ is reset in now reset in a beforeEach

* INT-3298: Removed old tests in NgModelTest.ts

* INT-3298: Enabled `destroyAfterEach` teardown option

* INT-3298: Refactored TestHooks.ts to account for teardown option being turned on now

* INT-3298: Refactored migrated tests to new TestHooks.ts changes

* INT-3298: Refactor to use `eachVersionContext`

* INT-3298: `editorHook` can now be used with a single standalone component, removing the need for editorHookStandalone

* INT-3298: Migrated EventBlacklistingTest.ts to BDD style

Also removed TestStore.ts as it's no longer needed.

* INT-3298: Added **/test/ts/**/*.ts to test eslint override

* INT-3298: Moved fakeType to TestHelpers.ts

* INT-3298: Added FormGroup test with default and onpush change detection

* INT-3299: Fixed id prop logging a warning when it shouldn't (#392)

* INT-3299: Check that an existing element with an id does not equal the current elementRef

* INT-3299: Added captureLogs function

* INT-3299: Added chai package for testing as well allowing it in eslint

* INT-3299: Added PropTest.ts

* INT-3299: Removed a comment

* INT-3299: Increased timeout

* INT-3299: use a `pTryUntil` instead of `waitForEditorsToLoad`

* INT-3298: Added a changelog entry
  • Loading branch information
danoaky-tiny authored Jul 8, 2024
1 parent 891859e commit cbd092a
Show file tree
Hide file tree
Showing 15 changed files with 4,285 additions and 4,000 deletions.
18 changes: 18 additions & 0 deletions .eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,24 @@
"quotes": [ "error", "single" ],
"semi": "error"
}
},
{
"files": [
"**/*Test.ts",
"**/test/**/*.ts"
],
"plugins": [
"chai-friendly"
],
"extends": [
"plugin:chai-friendly/recommended"
],
"rules": {
"no-unused-expressions": "off",
"no-console": "off",
"max-classes-per-file": "off",
"@typescript-eslint/no-non-null-assertion": "off"
}
}
],
"extends": [
Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Fixed
- Added rxjs ^7.4.0 as a peer dependency. Since last major release now uses rxjs v7 imports. #INT-3306
- `id` prop no longer logs a console warning on any use. #INT-3299

## 8.0.0 - 2024-04-29

Expand Down
3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,15 @@
"@tinymce/beehive-flow": "^0.19.0",
"@tinymce/eslint-plugin": "^2.3.1",
"@tinymce/miniature": "^6.0.0",
"@types/chai": "^4.3.16",
"@types/node": "^20.11.30",
"autoprefixer": "^10.4.19",
"babel-loader": "^9.1.3",
"chai": "^5.1.1",
"codelyzer": "^6.0.2",
"copyfiles": "^2.4.1",
"core-js": "^3.36.1",
"eslint-plugin-chai-friendly": "^1.0.0",
"eslint-plugin-storybook": "^0.8.0",
"gh-pages": "^6.1.0",
"json": "11.0.0",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,8 @@ export class EditorComponent extends Events implements AfterViewInit, ControlVal
const tagName = typeof this.tagName === 'string' ? this.tagName : 'div';
this._element = document.createElement(this.inline ? tagName : 'textarea');
if (this._element) {
if (document.getElementById(this.id)) {
const existingElement = document.getElementById(this.id);
if (existingElement && existingElement !== this._elementRef.nativeElement) {
/* eslint no-console: ["error", { allow: ["warn"] }] */
console.warn(`TinyMCE-Angular: an element with id [${this.id}] already exists. Editors with duplicate Id will not be able to mount`);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,6 @@ import 'zone.js/plugins/fake-async-test';
import { TestBed } from '@angular/core/testing';
import { BrowserDynamicTestingModule, platformBrowserDynamicTesting } from '@angular/platform-browser-dynamic/testing';

TestBed.initTestEnvironment(BrowserDynamicTestingModule, platformBrowserDynamicTesting());
TestBed.initTestEnvironment(BrowserDynamicTestingModule, platformBrowserDynamicTesting(), {
teardown: { destroyAfterEach: true },
});
60 changes: 60 additions & 0 deletions tinymce-angular-component/src/test/ts/alien/TestHelpers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import { Fun, Global, Arr, Strings } from '@ephox/katamari';
import { Observable, throwError, timeout } from 'rxjs';
import { ScriptLoader } from '../../../main/ts/utils/ScriptLoader';
import { Attribute, Remove, SelectorFilter, SugarElement } from '@ephox/sugar';
import { ComponentFixture } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import { EditorComponent } from '../../../main/ts/editor/editor.component';
import { Editor } from 'tinymce';
import { Keyboard, Keys } from '@ephox/agar';

export const apiKey = Fun.constant('qagffr3pkuv17a8on1afax661irst1hbr4e6tbv888sz91jc');

export const throwTimeout =
(timeoutMs: number, message: string = `Timeout ${timeoutMs}ms`) =>
<T>(source: Observable<T>) =>
source.pipe(
timeout({
first: timeoutMs,
with: () => throwError(() => new Error(message)),
})
);

export const deleteTinymce = () => {
ScriptLoader.reinitialize();

delete Global.tinymce;
delete Global.tinyMCE;

const hasTinyUri = (attrName: string) => (elm: SugarElement<Element>) =>
Attribute.getOpt(elm, attrName).exists((src) => Strings.contains(src, 'tinymce'));

const elements = Arr.flatten([
Arr.filter(SelectorFilter.all('script'), hasTinyUri('src')),
Arr.filter(SelectorFilter.all('link'), hasTinyUri('href')),
]);

Arr.each(elements, Remove.remove);
};

export const captureLogs = async (
method: 'log' | 'warn' | 'debug' | 'error',
fn: () => Promise<void> | void
): Promise<unknown[][]> => {
const original = console[method];
try {
const logs: unknown[][] = [];
console[method] = (...args: unknown[]) => logs.push(args);
await fn();
return logs;
} finally {
console[method] = original;
}
};

export const fakeTypeInEditor = (fixture: ComponentFixture<unknown>, str: string) => {
const editor: Editor = fixture.debugElement.query(By.directive(EditorComponent)).componentInstance.editor!;
editor.getBody().innerHTML = '<p>' + str + '</p>';
Keyboard.keystroke(Keys.space(), {}, SugarElement.fromDom(editor.getBody()));
fixture.detectChanges();
};
105 changes: 105 additions & 0 deletions tinymce-angular-component/src/test/ts/alien/TestHooks.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
import { after, before, beforeEach, context } from '@ephox/bedrock-client';
import { ComponentFixture, TestBed, TestModuleMetadata } from '@angular/core/testing';
import { Type } from '@angular/core';
import { EditorComponent, Version } from '../../../main/ts/editor/editor.component';
import { firstValueFrom, map, switchMap, tap } from 'rxjs';
import { By } from '@angular/platform-browser';
import { Optional, Singleton } from '@ephox/katamari';
import { VersionLoader } from '@tinymce/miniature';
import { deleteTinymce, throwTimeout } from './TestHelpers';
import { FormsModule, ReactiveFormsModule, NgModel } from '@angular/forms';
import { Editor } from 'tinymce';

export const fixtureHook = <T = unknown>(component: Type<T>, moduleDef: TestModuleMetadata) => {
before(async () => {
await TestBed.configureTestingModule(moduleDef).compileComponents();
});

return () => TestBed.createComponent(component);
};

export const tinymceVersionHook = (version: Version) => {
before(async () => {
await VersionLoader.pLoadVersion(version);
});
after(() => {
deleteTinymce();
});
};

export interface EditorFixture<T> extends ComponentFixture<T> {
editorComponent: EditorComponent;
editor: Editor;
ngModel: Optional<NgModel>;
}

export type CreateEditorFixture<T> = (
props?: Partial<
Omit<
EditorComponent,
`${'on' | 'ng' | 'register' | 'set' | 'write'}${string}` | 'createElement' | 'initialise' | 'editor'
>
>
) => Promise<EditorFixture<T>>;

export const editorHook = <T = unknown>(component: Type<T>, moduleDef: TestModuleMetadata = {
imports: [ component, EditorComponent, FormsModule, ReactiveFormsModule ],
}): CreateEditorFixture<T> => {
const createFixture = fixtureHook(component, moduleDef);
const editorFixture = Singleton.value<EditorFixture<T>>();
beforeEach(() => editorFixture.clear());

return async (props = {}) => {
if (editorFixture.isSet()) {
return editorFixture.get().getOrDie();
}

const fixture = createFixture();
const editorComponent =
fixture.componentInstance instanceof EditorComponent
? fixture.componentInstance
: Optional.from(fixture.debugElement.query(By.directive(EditorComponent)))
.map((v): EditorComponent => v.componentInstance)
.getOrDie('EditorComponent instance not found');

for (const [ key, value ] of Object.entries(props)) {
(editorComponent as any)[key] = value;
}

fixture.detectChanges();

return firstValueFrom(
editorComponent.onInit.pipe(
throwTimeout(10000, `Timed out waiting for editor to load`),
switchMap(
({ editor }) =>
new Promise<Editor>((resolve) => {
if (editor.initialized) {
resolve(editor);
}
editor.once('SkinLoaded', () => resolve(editor));
})
),
map(
(editor): EditorFixture<T> =>
Object.assign(fixture, {
editorComponent,
editor,
ngModel: Optional.from(fixture.debugElement.query(By.directive(EditorComponent))).bind((debugEl) =>
Optional.from(debugEl.injector.get<NgModel>(NgModel, undefined, { optional: true }))
),
})
),
tap(editorFixture.set)
)
);
};
};

export const eachVersionContext = (versions: Version[], fn: (version: Version) => void) =>
versions.forEach((version) =>
context(`With version ${version}`, () => {
tinymceVersionHook(version);
fn(version);
})
);
75 changes: 0 additions & 75 deletions tinymce-angular-component/src/test/ts/alien/TestStore.ts

This file was deleted.

Loading

0 comments on commit cbd092a

Please sign in to comment.