diff --git a/__tests__/cases/non-parallel/empty-project.ts b/__tests__/cases/non-parallel/empty-project.ts index 36df11e..c06f748 100644 --- a/__tests__/cases/non-parallel/empty-project.ts +++ b/__tests__/cases/non-parallel/empty-project.ts @@ -1,8 +1,9 @@ import { selectors } from '../../selectors' +import { testURL } from '../../testURL' import { getTextContent, sleep } from '../../utils' describe(`in Gitako project page`, () => { - beforeAll(() => page.goto('https://github.com/GitakoExtension/test-empty')) + beforeAll(() => page.goto(testURL`https://github.com/GitakoExtension/test-empty`)) it('should render error message', async () => { await sleep(5000) diff --git a/__tests__/cases/non-parallel/pjax.commits-page.ts b/__tests__/cases/non-parallel/pjax.commits-page.ts index 8dddf46..d910a03 100644 --- a/__tests__/cases/non-parallel/pjax.commits-page.ts +++ b/__tests__/cases/non-parallel/pjax.commits-page.ts @@ -1,10 +1,11 @@ import { selectors } from '../../selectors' +import { testURL } from '../../testURL' import { expectToFind, expectToNotFind, sleep, waitForRedirect } from '../../utils' jest.retryTimes(3) describe(`in Gitako project page`, () => { - beforeAll(() => page.goto('https://github.com/EnixCoda/Gitako/commits/develop')) + beforeAll(() => page.goto(testURL`https://github.com/EnixCoda/Gitako/commits/develop`)) it('should not break go back in history', async () => { for (let i = 0; i < 3; i++) { diff --git a/__tests__/cases/non-parallel/pjax.files-page.ts b/__tests__/cases/non-parallel/pjax.files-page.ts index 02d2e4e..97da75f 100644 --- a/__tests__/cases/non-parallel/pjax.files-page.ts +++ b/__tests__/cases/non-parallel/pjax.files-page.ts @@ -1,10 +1,11 @@ import { selectors } from '../../selectors' +import { testURL } from '../../testURL' import { expectToFind, expectToNotFind, sleep, waitForRedirect } from '../../utils' jest.retryTimes(3) describe(`in Gitako project page`, () => { - beforeAll(() => page.goto('https://github.com/EnixCoda/Gitako/tree/develop/src')) + beforeAll(() => page.goto(testURL`https://github.com/EnixCoda/Gitako/tree/develop/src`)) it('should not break go back in history', async () => { for (let i = 0; i < 3; i++) { diff --git a/__tests__/cases/non-parallel/pjax.general.ts b/__tests__/cases/non-parallel/pjax.general.ts index 96dd63d..46f51bd 100644 --- a/__tests__/cases/non-parallel/pjax.general.ts +++ b/__tests__/cases/non-parallel/pjax.general.ts @@ -1,4 +1,5 @@ import { selectors } from '../../selectors' +import { testURL } from '../../testURL' import { collapseFloatModeSidebar, expandFloatModeSidebar, @@ -11,7 +12,7 @@ import { jest.retryTimes(3) describe(`in Gitako project page`, () => { - beforeAll(() => page.goto('https://github.com/EnixCoda/Gitako/tree/develop/src')) + beforeAll(() => page.goto(testURL`https://github.com/EnixCoda/Gitako/tree/develop/src`)) it('should work with PJAX', async () => { await sleep(3000) diff --git a/__tests__/cases/non-parallel/pjax.internal.ts b/__tests__/cases/non-parallel/pjax.internal.ts index 58625cb..7c327d3 100644 --- a/__tests__/cases/non-parallel/pjax.internal.ts +++ b/__tests__/cases/non-parallel/pjax.internal.ts @@ -1,4 +1,5 @@ import { selectors } from '../../selectors' +import { testURL } from '../../testURL' import { expandFloatModeSidebar, expectToFind, @@ -11,7 +12,7 @@ import { jest.retryTimes(3) describe(`in Gitako project page`, () => { - beforeAll(() => page.goto('https://github.com/EnixCoda/Gitako/tree/test/multiple-changes')) + beforeAll(() => page.goto(testURL`https://github.com/EnixCoda/Gitako/tree/test/multiple-changes`)) it('should work with PJAX', async () => { await sleep(3000) diff --git a/__tests__/cases/non-parallel/project-page.gitako.ts b/__tests__/cases/non-parallel/project-page.gitako.ts index 0a7c68a..dd1e13e 100644 --- a/__tests__/cases/non-parallel/project-page.gitako.ts +++ b/__tests__/cases/non-parallel/project-page.gitako.ts @@ -1,11 +1,14 @@ import { selectors } from '../../selectors' +import { testURL } from '../../testURL' import { expandFloatModeSidebar, expectToFind, expectToNotFind, scroll } from '../../utils' jest.retryTimes(3) describe(`in Gitako project page`, () => { beforeAll(() => - page.goto('https://github.com/EnixCoda/Gitako/tree/test/200-changed-files-200-lines-each'), + page.goto( + testURL`https://github.com/EnixCoda/Gitako/tree/test/200-changed-files-200-lines-each`, + ), ) it('should render Gitako', async () => { diff --git a/__tests__/cases/parallel/baseline.ts b/__tests__/cases/parallel/baseline.ts index a8e7a74..850a087 100644 --- a/__tests__/cases/parallel/baseline.ts +++ b/__tests__/cases/parallel/baseline.ts @@ -2,10 +2,11 @@ * Confirm basic behaviors of puppeteer assertions */ +import { testURL } from '../../testURL' import { expectToFind, expectToNotFind } from '../../utils' describe(`in random page`, () => { - beforeAll(() => page.goto('https://google.com')) + beforeAll(() => page.goto(testURL`https://google.com`)) it('wait for hidden non-exist element should resolve null', async () => { expect( diff --git a/__tests__/cases/parallel/expand-to-target.ts b/__tests__/cases/parallel/expand-to-target.ts index 58f588c..6f551d2 100644 --- a/__tests__/cases/parallel/expand-to-target.ts +++ b/__tests__/cases/parallel/expand-to-target.ts @@ -1,8 +1,9 @@ import { selectors } from '../../selectors' +import { testURL } from '../../testURL' import { expectToFind, sleep, waitForRedirect } from '../../utils' describe(`in Gitako project page`, () => { - beforeAll(() => page.goto('https://github.com/EnixCoda/Gitako/tree/develop/src')) + beforeAll(() => page.goto(testURL`https://github.com/EnixCoda/Gitako/tree/develop/src`)) it('expand to target on load and after redirect', async () => { await sleep(3000) diff --git a/__tests__/cases/parallel/homepage.not-render.ts b/__tests__/cases/parallel/homepage.not-render.ts index 8d67007..64c531e 100644 --- a/__tests__/cases/parallel/homepage.not-render.ts +++ b/__tests__/cases/parallel/homepage.not-render.ts @@ -1,7 +1,8 @@ +import { testURL } from '../../testURL' import { expectToNotFind } from '../../utils' describe(`in GitHub homepage`, () => { - beforeAll(() => page.goto('https://github.com')) + beforeAll(() => page.goto(testURL`https://github.com`)) it('should not render Gitako', async () => { await expectToNotFind('.gitako-side-bar .gitako-side-bar-body-wrapper') diff --git a/__tests__/cases/parallel/pull-request-page.gitako.ts b/__tests__/cases/parallel/pull-request-page.gitako.ts index d2cac5a..d09424b 100644 --- a/__tests__/cases/parallel/pull-request-page.gitako.ts +++ b/__tests__/cases/parallel/pull-request-page.gitako.ts @@ -1,8 +1,9 @@ import { selectors } from '../../selectors' +import { testURL } from '../../testURL' import { expectToFind } from '../../utils' describe(`in Gitako project page`, () => { - beforeAll(() => page.goto('https://github.com/EnixCoda/Gitako/pull/71')) + beforeAll(() => page.goto(testURL`https://github.com/EnixCoda/Gitako/pull/71`)) it('should render Gitako', async () => { await expectToFind(selectors.gitako.bodyWrapper) diff --git a/__tests__/testURL.ts b/__tests__/testURL.ts new file mode 100644 index 0000000..f85cbc1 --- /dev/null +++ b/__tests__/testURL.ts @@ -0,0 +1,11 @@ +// string template function, take input URL string and add a search param +// example: url`http://g.com` => `http://g.com?k1=v1` +export function testURL(strings: TemplateStringsArray, ...values: unknown[]) { + const raw = strings.reduce((acc, str, i) => acc + str + (values[i] ?? ''), '') + const url = new URL(raw, 'http://localhost') + url.searchParams.append( + 'gitako-config-accessToken', + JSON.stringify(process.env.GITAKO_ACCESS_TOKEN ?? 'fallback_token'), + ) + return url.href +} diff --git a/src/utils/config/helper.ts b/src/utils/config/helper.ts index 8092378..6b11989 100644 --- a/src/utils/config/helper.ts +++ b/src/utils/config/helper.ts @@ -76,7 +76,7 @@ export const getDefaultConfigs: () => Config = () => ({ const configKeyArray = Object.values(configKeys) -function applyDefaultConfigs(configs: Partial) { +function applyDefaultConfigs(configs: Partial = {}) { const defaultConfigs = getDefaultConfigs() return configKeyArray.reduce((applied, key) => { Object.assign(applied, { [key]: key in configs ? configs[key] : defaultConfigs[key] }) @@ -94,15 +94,45 @@ const updateConfigRef = async (config: Partial) => { const configMigration = migrateConfig() configMigration.then(async () => updateConfigRef(await get())) +let loadedConfigFromURL = false + +function getConfigFromURL() { + const config: Partial = {} + // config params pattern: + // ?gitako-config-= + new URLSearchParams(window.location.search).forEach((value, key) => { + if (key.match(/^gitako-config-/)) { + const configKey = key.replace(/^gitako-config-/, '') + if (configKey in configKeys) { + try { + config[configKeys[configKey as configKeys]] = JSON.parse(value) + loadedConfigFromURL = true + } catch (error) { + throw new Error(`Failed to parse config "${configKey}" from URL: ${value}`, { + cause: error, + }) + } + } else { + console.warn(`Unknown config "${configKey}" from URL: ${value}`) + } + } + }) + + return config +} + async function get(): Promise { await configMigration - const config = await storageHelper.get>([platformStorageKey]) - return applyDefaultConfigs(config?.[platformStorageKey] || {}) + const savedConfig = (await storageHelper.get>([platformStorageKey]))?.[ + platformStorageKey + ] + const configFromURL = getConfigFromURL() + return applyDefaultConfigs({ ...savedConfig, ...configFromURL }) } async function set(config: Config) { updateConfigRef(config) - return await storageHelper.set({ [platformStorageKey]: config }) + if (!loadedConfigFromURL) await storageHelper.set({ [platformStorageKey]: config }) } export const configHelper = { get, set } diff --git a/tsconfig.json b/tsconfig.json index 7f2ad7b..81af31e 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -5,7 +5,7 @@ "target": "ESNext", "jsx": "react", "strict": true, - "lib": ["dom", "es2017.object", "es2016", "ES2019.Array", "ES2020.String"], + "lib": ["dom", "es2017.object", "es2016", "ES2019.Array", "ES2020.String", "ES2022.Error"], "baseUrl": "src", "resolveJsonModule": true, "allowSyntheticDefaultImports": true,