From 78be797466c2d8ae256fbe9cfa7f0736654b9468 Mon Sep 17 00:00:00 2001 From: Simon Li Date: Fri, 15 Dec 2023 00:04:13 +0000 Subject: [PATCH] Test autodetect.js --- .eslintrc.js | 2 + .../binderhub-client/lib/autodetect.js | 9 +- .../binderhub-client/tests/autodetect.test.js | 116 ++++++++++++++++++ .../tests/fixtures/mybinder.config.json | 31 +++++ 4 files changed, 150 insertions(+), 8 deletions(-) create mode 100644 js/packages/binderhub-client/tests/autodetect.test.js create mode 100644 js/packages/binderhub-client/tests/fixtures/mybinder.config.json diff --git a/.eslintrc.js b/.eslintrc.js index 78b7288cb..9ce037dae 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -3,6 +3,8 @@ module.exports = { browser: true, jquery: true, "jest/globals": true, + node: true, + es6: true, }, extends: ["eslint:recommended"], parser: "@babel/eslint-parser", diff --git a/js/packages/binderhub-client/lib/autodetect.js b/js/packages/binderhub-client/lib/autodetect.js index 45431f102..47ae6ae42 100644 --- a/js/packages/binderhub-client/lib/autodetect.js +++ b/js/packages/binderhub-client/lib/autodetect.js @@ -1,10 +1,3 @@ -import { fetch as fetchPolyfill } from "whatwg-fetch"; - -// Use native browser fetch if available, and use the polyfill if not available -// (e.g. in tests https://github.com/jestjs/jest/issues/13834#issuecomment-1407375787) -// @todo: this is only a problem in the jest tests, so get rid of this and mock fetch instead -const fetch = window.fetch || fetchPolyfill; - /** * Dict holding cached values of API request to _config endpoint */ @@ -50,7 +43,7 @@ export async function detect(baseUrl, text) { return { providerPrefix: provider, repository: m.groups.repo, - ref: m.groups.ref, + ref: m.groups.ref || null, path: m.groups.filepath || m.groups.urlpath || null, pathType: m.groups.filepath ? "filepath" diff --git a/js/packages/binderhub-client/tests/autodetect.test.js b/js/packages/binderhub-client/tests/autodetect.test.js new file mode 100644 index 000000000..09321a5dc --- /dev/null +++ b/js/packages/binderhub-client/tests/autodetect.test.js @@ -0,0 +1,116 @@ +import { getRepoProviders, detect } from "../lib/autodetect"; +import { readFileSync } from "node:fs"; + +const mybinderConfig = JSON.parse( + readFileSync(`${__dirname}/fixtures/mybinder.config.json`, { + encoding: "utf-8", + }), +); + +// Mock fetch() +// https://www.leighhalliday.com/mock-fetch-jest +global.fetch = jest.fn((url) => { + if (url == "https://binder.example.org/_config") { + return Promise.resolve({ + json: () => Promise.resolve(mybinderConfig), + }); + } + return Promise.reject(`Unexpected URL ${url}`); +}); + +beforeEach(() => { + fetch.mockClear(); +}); + +test("getRepoProviders requests the repo provider configs", async () => { + const config = await getRepoProviders("https://binder.example.org"); + expect(config).toEqual(mybinderConfig); +}); + +test("detect returns null if no provider matches", async () => { + const result = await detect( + "https://binder.example.org", + "https://github.com/binder-examples/conda/pulls", + ); + expect(result).toBeNull(); +}); + +test("detect parses a repo with no path", async () => { + const expected = { + providerPrefix: "gh", + repository: "binder-examples/conda", + ref: null, + path: null, + pathType: null, + providerName: "Fake GitHub", + }; + const result = await detect( + "https://binder.example.org", + "https://github.com/binder-examples/conda", + ); + expect(result).toEqual(expected); +}); + +test("detect parses a repo with a ref but no path", async () => { + const expected = { + providerPrefix: "gh", + repository: "binder-examples/conda", + ref: "abc", + path: null, + pathType: null, + providerName: "Fake GitHub", + }; + const result = await detect( + "https://binder.example.org", + "https://github.com/binder-examples/conda/tree/abc", + ); + expect(result).toEqual(expected); +}); + +test("detect parses a repo with a ref and file path", async () => { + const expected = { + providerPrefix: "gh", + repository: "binder-examples/conda", + ref: "f00a783", + path: "index.ipynb", + pathType: "filepath", + providerName: "Fake GitHub", + }; + const result = await detect( + "https://binder.example.org", + "https://github.com/binder-examples/conda/blob/f00a783/index.ipynb", + ); + expect(result).toEqual(expected); +}); + +test("detect parses a repo with a ref and directory path", async () => { + const expected = { + providerPrefix: "gh", + repository: "binder-examples/conda", + ref: "f00a783", + path: ".github/workflows", + pathType: "urlpath", + providerName: "Fake GitHub", + }; + const result = await detect( + "https://binder.example.org", + "https://github.com/binder-examples/conda/tree/f00a783/.github/workflows", + ); + expect(result).toEqual(expected); +}); + +test("detect checks other repo providers", async () => { + const expected = { + providerPrefix: "gl", + repository: "gitlab-org/gitlab-foss", + ref: "v16.4.4", + path: "README.md", + pathType: "filepath", + providerName: "GitLab.com", + }; + const result = await detect( + "https://binder.example.org", + "https://gitlab.com/gitlab-org/gitlab-foss/-/blob/v16.4.4/README.md", + ); + expect(result).toEqual(expected); +}); diff --git a/js/packages/binderhub-client/tests/fixtures/mybinder.config.json b/js/packages/binderhub-client/tests/fixtures/mybinder.config.json new file mode 100644 index 000000000..f44b68b12 --- /dev/null +++ b/js/packages/binderhub-client/tests/fixtures/mybinder.config.json @@ -0,0 +1,31 @@ +{ + "gh": { + "text": "Fake Provider", + "tag_text": "Fake Ref", + "ref_prop_disabled": true, + "label_prop_disabled": true, + "display_name": "Fake GitHub", + "regex_detect": [ + "^https://github\\.com/(?[^/]+/[^/]+)(/blob/(?[^/]+)(/(?.+))?)?$", + "^https://github\\.com/(?[^/]+/[^/]+)(/tree/(?[^/]+)(/(?.+))?)?$" + ] + }, + "gl": { + "text": "GitLab.com repository or URL", + "tag_text": "Git ref (branch, tag, or commit)", + "ref_prop_disabled": false, + "label_prop_disabled": false, + "display_name": "GitLab.com", + "regex_detect": [ + "^https://gitlab\\.com/(?[^/]+/[^/]+(/[^/-][^/]+)*)(/-/blob/(?[^/]+)(/(?.+))?)?$", + "^https://gitlab\\.com/(?[^/]+/[^/]+(/[^/-][^/]+)*)(/-/tree/(?[^/]+)(/(?.+))?)?$" + ] + }, + "nore": { + "text": "Fake No Regex Provider", + "tag_text": "Fake Ref", + "ref_prop_disabled": true, + "label_prop_disabled": true, + "display_name": "Fake No Regex" + } +}