Skip to content

Commit

Permalink
Automatically assign mocha-remote context on this (#110)
Browse files Browse the repository at this point in the history
* Update @react-native/eslint-config to version 0.74.75 (#109)

Co-authored-by: depfu[bot] <23717796+depfu[bot]@users.noreply.github.com>

* Passing mocha-remote context through RN component

* Fixing dependencies

* Fixing client tests

* Assigning Mocha Remote context into the suite context

* Adding test which fails conditionally on the context

* Nuked the package lock

---------

Co-authored-by: depfu[bot] <23717796+depfu[bot]@users.noreply.github.com>
  • Loading branch information
kraenhansen and depfu[bot] authored Mar 19, 2024
1 parent b8a3423 commit dc477da
Show file tree
Hide file tree
Showing 9 changed files with 3,067 additions and 1,933 deletions.
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

0 comments on commit dc477da

Please sign in to comment.