feat: support setting temporary config from URL

This commit is contained in:
EnixCoda 2023-12-15 00:13:51 +08:00
parent c88b817d60
commit 69cd8d71a7
13 changed files with 68 additions and 15 deletions

View file

@ -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)

View file

@ -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++) {

View file

@ -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++) {

View file

@ -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)

View file

@ -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)

View file

@ -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 () => {

View file

@ -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(

View file

@ -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)

View file

@ -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')

View file

@ -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)

11
__tests__/testURL.ts Normal file
View file

@ -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
}

View file

@ -76,7 +76,7 @@ export const getDefaultConfigs: () => Config = () => ({
const configKeyArray = Object.values(configKeys)
function applyDefaultConfigs(configs: Partial<Config>) {
function applyDefaultConfigs(configs: Partial<Config> = {}) {
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<Config>) => {
const configMigration = migrateConfig()
configMigration.then(async () => updateConfigRef(await get()))
let loadedConfigFromURL = false
function getConfigFromURL() {
const config: Partial<Config> = {}
// config params pattern:
// ?gitako-config-<key>=<json-value>
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<Config> {
await configMigration
const config = await storageHelper.get<Record<string, Config>>([platformStorageKey])
return applyDefaultConfigs(config?.[platformStorageKey] || {})
const savedConfig = (await storageHelper.get<Record<string, Config>>([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 }

View file

@ -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,