refactor: add ScriptRunner class
Change-Id: I118adb9ec338e88b40321208b84228886bb6b590
diff --git a/src/common/architecture/scripts/ScriptRunner.test.ts b/src/common/architecture/scripts/ScriptRunner.test.ts
new file mode 100644
index 0000000..7435c8e
--- /dev/null
+++ b/src/common/architecture/scripts/ScriptRunner.test.ts
@@ -0,0 +1,83 @@
+import Script, {
+ ScriptEnvironment,
+ ScriptPage,
+ ScriptRunPhase,
+} from './Script';
+import { beforeEach, expect, it, jest } from '@jest/globals';
+import ScriptRunner from './ScriptRunner';
+
+interface FakeScriptOptions {
+ id: string;
+ priority: number;
+}
+
+class FakeScript extends Script {
+ id: string;
+ priority: number;
+ page: ScriptPage.CommunityConsole;
+ environment: ScriptEnvironment.ContentScript;
+ runPhase: ScriptRunPhase.Main;
+
+ constructor(options: FakeScriptOptions) {
+ super();
+ this.id = options.id;
+ this.priority = options.priority;
+ }
+
+ execute() {}
+}
+
+const fakeScriptMock = jest
+ .spyOn(FakeScript.prototype, 'execute')
+ .mockImplementation(function() {
+ return (this as FakeScript).id;
+ });
+
+beforeEach(() => {
+ jest.clearAllMocks();
+});
+
+it('scripts run in the correct order based on priority', () => {
+ const scriptsConfig = [
+ {
+ script: new FakeScript({
+ id: '1',
+ priority: 1,
+ }),
+ expectedRunPosition: 2,
+ },
+ {
+ script: new FakeScript({
+ id: '2',
+ priority: 1000,
+ }),
+ expectedRunPosition: 3,
+ },
+ {
+ script: new FakeScript({
+ id: '3',
+ priority: 0,
+ }),
+ expectedRunPosition: 1,
+ },
+ {
+ script: new FakeScript({
+ id: '4',
+ priority: 2 ** 31,
+ }),
+ expectedRunPosition: 4,
+ },
+ ];
+
+ const scriptRunner = new ScriptRunner();
+ scriptRunner.add(...scriptsConfig.map((config) => config.script));
+ scriptRunner.run();
+
+ expect(fakeScriptMock).toHaveBeenCalledTimes(scriptsConfig.length);
+ for (const config of scriptsConfig) {
+ expect(fakeScriptMock).toHaveNthReturnedWith(
+ config.expectedRunPosition,
+ config.script.id,
+ );
+ }
+});
diff --git a/src/common/architecture/scripts/ScriptRunner.ts b/src/common/architecture/scripts/ScriptRunner.ts
new file mode 100644
index 0000000..4a2ed2d
--- /dev/null
+++ b/src/common/architecture/scripts/ScriptRunner.ts
@@ -0,0 +1,20 @@
+import Script from './Script';
+
+export default class ScriptRunner {
+ private scripts: Script[] = [];
+
+ add(...scripts: Script[]) {
+ this.scripts.push(...scripts);
+ }
+
+ run() {
+ this.scripts.sort((a, b) => {
+ if (a.priority < b.priority) return -1;
+ if (a.priority > b.priority) return 1;
+ return 0;
+ });
+ for (const script of this.scripts) {
+ script.execute();
+ }
+ }
+}
diff --git a/src/features/Features.ts b/src/features/Features.ts
index 98a4b96..8a13700 100644
--- a/src/features/Features.ts
+++ b/src/features/Features.ts
@@ -4,6 +4,7 @@
ScriptPage,
ScriptRunPhase,
} from '../common/architecture/scripts/Script';
+import ScriptRunner from '../common/architecture/scripts/ScriptRunner';
import AutoRefreshFeature from './autoRefresh/autoRefresh.feature';
import InfiniteScrollFeature from './infiniteScroll/infiniteScroll.feature';
@@ -22,13 +23,11 @@
];
private initializedFeatures: Feature[];
- runScripts(context: Context) {
- const scripts = this.getScripts(context).sort((a, b) =>
- a.priority < b.priority ? -1 : 1,
- );
- for (const script of scripts) {
- script.execute();
- }
+ getScriptRunner(context: Context) {
+ const scripts = this.getScripts(context);
+ const scriptRunner = new ScriptRunner();
+ scriptRunner.add(...scripts);
+ return scriptRunner;
}
getScripts(context: Context) {
diff --git a/src/platforms/communityConsole/entryPoints/main.ts b/src/platforms/communityConsole/entryPoints/main.ts
index c7d223b..03d5eba 100644
--- a/src/platforms/communityConsole/entryPoints/main.ts
+++ b/src/platforms/communityConsole/entryPoints/main.ts
@@ -4,13 +4,18 @@
ScriptRunPhase,
} from '../../../common/architecture/scripts/Script';
import Features from '../../../features/Features';
+import ScriptRunner from '../../../common/architecture/scripts/ScriptRunner';
// Run legacy Javascript entry point
import '../../../contentScripts/communityConsole/main';
const features = new Features();
-features.runScripts({
+const scripts = features.getScripts({
page: ScriptPage.CommunityConsole,
environment: ScriptEnvironment.ContentScript,
runPhase: ScriptRunPhase.Main,
});
+
+const scriptRunner = new ScriptRunner();
+scriptRunner.add(...scripts);
+scriptRunner.run();
diff --git a/src/platforms/communityConsole/entryPoints/start.ts b/src/platforms/communityConsole/entryPoints/start.ts
index b7cb6eb..2410f2c 100644
--- a/src/platforms/communityConsole/entryPoints/start.ts
+++ b/src/platforms/communityConsole/entryPoints/start.ts
@@ -4,13 +4,18 @@
ScriptRunPhase,
} from '../../../common/architecture/scripts/Script';
import Features from '../../../features/Features';
+import ScriptRunner from '../../../common/architecture/scripts/ScriptRunner';
// Run legacy Javascript entry point
import '../../../contentScripts/communityConsole/start';
const features = new Features();
-features.runScripts({
+const scripts = features.getScripts({
page: ScriptPage.CommunityConsole,
environment: ScriptEnvironment.ContentScript,
runPhase: ScriptRunPhase.Start,
});
+
+const scriptRunner = new ScriptRunner();
+scriptRunner.add(...scripts);
+scriptRunner.run();