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

Automatically assign mocha-remote context on this #110

Merged
merged 7 commits into from
Mar 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions examples/expo/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,11 @@
"expo-status-bar": "~1.11.1",
"mocha-remote-react-native": "1.9.0",
"react": "18.2.0",
"react-native": "0.73.6"
"react-native": "0.73.5"
},
"devDependencies": {
"@babel/core": "^7.20.0",
"@react-native/eslint-config": "0.73.2",
"@react-native/eslint-config": "0.74.75",
"@types/react": "~18.2.45"
},
"eslintConfig": {
Expand Down
6 changes: 6 additions & 0 deletions examples/expo/simple.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,10 @@ describe("A test suite", () => {
// It might take some time to succeed again
setTimeout(done, 500);
});

it("can fail if the context needs it to", function() {
if (this.shouldThrow) {
throw new Error("Expected error!");
}
});
});
4,897 changes: 2,996 additions & 1,901 deletions package-lock.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
],
"scripts": {
"lint": "eslint .",
"build": "nx build mocha-remote",
"build": "nx run-many -t build",
"test": "nx run-many -t test"
},
"author": {
Expand Down
51 changes: 34 additions & 17 deletions packages/client/src/Client.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { expect } from 'chai';
import { WebSocketServer } from "ws";
import { WebSocketServer, AddressInfo } from "ws";
import * as flatted from "flatted";

import { Client } from './Client';
Expand Down Expand Up @@ -46,11 +46,12 @@ describe("Mocha Remote Client", () => {
// We expect that no tests are loaded before running
expect(client.suite.tests.length).equals(0);

const failures = await new Promise(async resolve => {
const runner = await client.run(resolve);
// The total number of tests should only include grepped
expect(runner.total).equals(2);
})
const failures = await new Promise(resolve => {
client.run(resolve).then(runner => {
// The total number of tests should only include grepped
expect(runner.total).equals(2);
});
});

// We expect that all tests has been loaded now
expect(client.suite.tests.length).equals(3);
Expand Down Expand Up @@ -107,14 +108,28 @@ describe("Mocha Remote Client", () => {
autoConnect: false,
context,
tests: actualContext => {
expect(actualContext).deep.equals({ ...context, ...updates });
const expectedContext = { ...context, ...updates };
expect(actualContext).deep.equals(expectedContext);

it("passes context through this", function(this: Mocha.Context) {
// Looping expected keys to avoid
for (const key of Object.keys(expectedContext)) {
expect(expectedContext[key]).equals(this[key]);
}
});
}
});

await new Promise(resolve => client.run(resolve));
{
const failures = await new Promise<number>((resolve, reject) => client.run(resolve).catch(reject));
expect(failures).equals(0);
}
// Increase the run count and run again, providing the updated value an update to the context when running
updates.run = 1;
await new Promise(resolve => client.run(resolve, { context: { run: 1 } }));
{
const failures = await new Promise<number>((resolve, reject) => client.run(resolve, { context: { run: 1 } }).catch(reject));
expect(failures).equals(0);
}
});

it("re-runs", async () => {
Expand All @@ -132,9 +147,10 @@ describe("Mocha Remote Client", () => {
// We expect that no tests are loaded before running
expect(client.suite.tests.length).equals(0);

const failures1 = await new Promise(async resolve => {
const runner = await client.run(resolve);
expect(runner.total).equals(1);
const failures1 = await new Promise(resolve => {
client.run(resolve).then(runner => {
expect(runner.total).equals(1);
});
})
// We expect that all tests has been loaded now
expect(client.suite.tests.length).equals(1);
Expand All @@ -144,9 +160,10 @@ describe("Mocha Remote Client", () => {

// One more time

const failures2 = await new Promise(async resolve => {
const runner = await client.run(resolve);
expect(runner.total).equals(1);
const failures2 = await new Promise(resolve => {
client.run(resolve).then(runner => {
expect(runner.total).equals(1);
});
})

// We expect that all tests has been loaded now
Expand Down Expand Up @@ -182,7 +199,7 @@ describe("Mocha Remote Client", () => {
});

it("reconnects until server is up", async () => {
const { port } = wss.address() as WebSocket.AddressInfo;
const { port } = wss.address() as AddressInfo;
// Shut down the server before the client gets a chance to connect
wss.close();
// Start connecting
Expand Down Expand Up @@ -295,7 +312,7 @@ describe("Mocha Remote Client", () => {
}));

ws.on("message", data => {
const msg = flatted.parse(data as string);
const msg = flatted.parse(data.toString());
expect(msg.action).equals("error");
expect(msg.message).equals("b00m!");
resolve();
Expand Down
2 changes: 2 additions & 0 deletions packages/client/src/Client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,8 @@ export class Client extends ClientEventEmitter {
// Building a fake file path to emit some path via events
const fakeFilePath = "/mocha-remote-client/mocked-test-suite.js";
this.suite.emit(EVENT_FILE_PRE_REQUIRE, global, fakeFilePath, mocha);
// Assing in the context to make it available in hooks
Object.assign(this.suite.ctx, context);
// We're treating the value returned from the `result` as the `module.exports` from a file.
const result = await this.config.tests(context);
this.suite.emit(EVENT_FILE_REQUIRE, result, fakeFilePath, mocha);
Expand Down
2 changes: 2 additions & 0 deletions packages/client/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,5 @@ export { serialization };

export * from "./Client";
export * from "./ClientEventEmitter";

export type { CustomContext, MochaConfig } from "mocha-remote-common";
3 changes: 3 additions & 0 deletions packages/react-native/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@
"scripts": {
"build": "tsc"
},
"dependencies": {
"mocha-remote-client": "1.9.0"
},
"peerDependencies": {
"react-native": "*",
"react": "^18"
Expand Down
33 changes: 21 additions & 12 deletions packages/react-native/src/index.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import React, { useEffect, useState, createContext, useContext } from "react";
import { StyleSheet, Text, View, Platform, TextProps, SafeAreaView } from 'react-native';
import { Text, Platform, TextProps } from 'react-native';

import { Client } from "mocha-remote-client";
import { Client, CustomContext } from "mocha-remote-client";

type Status =
export type { CustomContext };

export type Status =
| {
kind: "waiting";
}
Expand All @@ -20,31 +22,38 @@ type Status =
totalTests: number;
}

type MochaRemoteProviderProps = React.PropsWithChildren<{
export type MochaRemoteProviderProps = React.PropsWithChildren<{
title?: string;
tests: () => void;
tests: (context: CustomContext) => void;
}>;

type MochaRemoteContextValue = {
export type MochaRemoteContextValue = {
connected: boolean;
status: Status;
context: CustomContext;
};

export const MochaRemoteContext = createContext<MochaRemoteContextValue>({ connected: false, status: { kind: "waiting" } });
export const MochaRemoteContext = createContext<MochaRemoteContextValue>({
connected: false,
status: { kind: "waiting" },
context: {},
});

export function MochaRemoteProvider({ children, tests, title = `React Native on ${Platform.OS}` }: MochaRemoteProviderProps) {
const [connected, setConnected] = useState(false);
const [status, setStatus] = useState<Status>({ kind: "waiting" });
const [context, setContext] = useState<CustomContext>({});
useEffect(() => {
const client = new Client({
title,
tests() {
tests(context) {
setContext(context);
// Adding an async hook before each test to allow the UI to update
beforeEach(() => {
beforeEach("async-pause", () => {
return new Promise<void>((resolve) => setImmediate(resolve));
});
// Require in the tests
tests();
tests(context);
},
})
.on("connection", () => {
Expand Down Expand Up @@ -86,10 +95,10 @@ export function MochaRemoteProvider({ children, tests, title = `React Native on
return () => {
client.disconnect();
};
}, [setStatus]);
}, [setStatus, setContext]);

return (
<MochaRemoteContext.Provider value={{status, connected}}>
<MochaRemoteContext.Provider value={{status, connected, context}}>
{children}
</MochaRemoteContext.Provider>
);
Expand Down
Loading