github.com/quickfeed/quickfeed@v0.0.0-20240507093252-ed8ca812a09c/public/src/__tests__/TestHelpers.ts (about) 1 import { createOvermindMock } from "overmind" 2 import { Browser, Builder, IRectangle, ThenableWebDriver } from "selenium-webdriver" 3 import { config } from "../overmind" 4 import { State } from "../overmind/state" 5 import { SubType } from "overmind/lib/internalTypes" 6 import { ReviewState } from "../overmind/namespaces/review/state" 7 import { ApiClient } from "../overmind/effects" 8 9 export const isOverlapping = (rect: IRectangle, rect2: IRectangle) => { 10 return (rect.x < rect2.x + rect2.width && 11 rect.x + rect.width > rect2.x && 12 rect.y < rect2.y + rect2.height && 13 rect.height + rect.y > rect2.y) 14 } 15 16 // getBuilders returns an array of builders for all the browsers that are supported. 17 // Supported browsers must be defined in the config.json file. 18 // These builders require you to have web driver executables in your PATH. 19 const getBuilders = (): Builder[] => { 20 const config = require("./config.json") 21 const builders: Builder[] = [] 22 Object.entries(Browser).forEach(([key, value]) => { 23 if (key in config.BROWSERS && config.BROWSERS[key]) { 24 const builder = createBuilder(value) 25 builders.push(builder) 26 } 27 }) 28 if (builders.length === 0) { 29 throw new Error("No supported browsers found. Please check the config.json file.") 30 } 31 return builders 32 } 33 34 const createBuilder = (browser: string) => { 35 return new Builder().forBrowser(browser) 36 } 37 38 // getBaseUrl returns the base url to be used for the tests. 39 export const getBaseUrl = (): string => { 40 const config = require("./config.json") 41 let url = config.BASE_URL as string 42 if (url.endsWith("/")) { 43 url = url.slice(0, -1) 44 } 45 return url 46 } 47 48 /** 49 * setupDrivers returns an array of drivers for all the browsers that are supported. 50 * @path (optional) the path to load in the browser. 51 * @example: setupDrivers("/path/to/page") 52 */ 53 export const setupDrivers = (path?: string): ThenableWebDriver[] => { 54 const baseUrl = getBaseUrl() 55 const builders = getBuilders() 56 const drivers = builders.map(driver => driver.build()) 57 58 beforeAll(async () => { 59 // Open the page to be tested in all browsers, before running tests 60 await Promise.all(drivers.map(driver => driver.get(baseUrl + (path ? path : "")))) 61 }) 62 63 afterAll(async () => { 64 // Close all drivers after the tests are done 65 await Promise.all(drivers.map(driver => driver.quit())) 66 }) 67 68 return drivers 69 } 70 71 /** initializeOvermind creates a mock Overmind instance with the given state, reviewState, and mockedEffects. 72 * @param state the state to initialize the mock with 73 * @param mockedEffects the mocked effects to initialize the mock with 74 * NOTE: Directly setting derived values in the state is not supported. 75 */ 76 export const initializeOvermind = (state: Partial<State & SubType<{ review: Partial<ReviewState>; }, object>>, mockedApi?: ApiClient) => { 77 const overmind = createOvermindMock(config, { 78 api: mockedApi 79 }, initialState => { 80 Object.assign(initialState, state) 81 }); 82 Object.assign(overmind.effects.api, mockedApi) 83 return overmind 84 } 85 86 /** UnaryApiClient is a type that represents the ApiClient without streaming methods. */ 87 interface UnaryApiClient { 88 client: Omit<ApiClient["client"], "submissionStream">; 89 } 90 91 /** Methods is a type that represents the methods of the UnaryApiClient */ 92 type Methods = UnaryApiClient["client"]; 93 94 /** mock is a helper function that takes a method and a mocked function to run in place of the method. 95 * It returns a function that can be used to replace the method in the ApiClient. 96 * @param _method the method to mock 97 * @param mockFn the function to run in place of the method 98 * @example: mock("getSubmission", async (req) => { return { error: null, message: new Submission() } }) 99 */ 100 export function mock<T extends keyof Methods>( 101 _method: T, 102 mockFn: (req: Parameters<Methods[T]>[0]) => ReturnType<Methods[T]> 103 ): Methods[T] { 104 return async function (...args: any[]): Promise<any> { 105 return mockFn(args); 106 }; 107 }