Fix for first run wizard in single tree installs (#1444)

This commit is contained in:
David Straub
2026-09-17 12:41:09 +02:00
committed by GitHub
parent e826600507
commit d111e000bc
2 changed files with 62 additions and 4 deletions
+8 -3
View File
@@ -95,6 +95,7 @@ class GrampsjsFirstRun extends GrampsjsAppStateMixin(LitElement) {
_errorConfig: {type: String},
_errorTree: {type: String},
_tree: {type: String},
_hasTree: {type: Boolean},
}
}
@@ -108,6 +109,9 @@ class GrampsjsFirstRun extends GrampsjsAppStateMixin(LitElement) {
this._errorConfig = ''
this._errorTree = ''
this._tree = ''
// True once the owner's login token carries a tree claim, which is the
// case in single-tree installs, where no tree needs to be created.
this._hasTree = false
}
// Drives the confirmation field's own validity, so checkValidity() and the
@@ -297,7 +301,7 @@ class GrampsjsFirstRun extends GrampsjsAppStateMixin(LitElement) {
this.stateUser,
this._errorUser
)}
${this._tree
${this._tree || this._hasTree
? ''
: this._showProgress(
this._('Creating your first tree'),
@@ -315,7 +319,7 @@ class GrampsjsFirstRun extends GrampsjsAppStateMixin(LitElement) {
<div
style="visibility:${this.stateUser === STATE_DONE &&
(this._tree || this.stateTree === STATE_DONE) &&
(this._tree || this._hasTree || this.stateTree === STATE_DONE) &&
this.stateConfig !== STATE_PROGRESS
? 'visible'
: 'hidden'};"
@@ -366,8 +370,9 @@ class GrampsjsFirstRun extends GrampsjsAppStateMixin(LitElement) {
this._errorUser = resp.error || ''
return
}
this._hasTree = !!getTreeFromToken(localStorage.getItem('access_token'))
if (!this._tree) {
if (!this._tree && !this._hasTree) {
await this._submitTree()
if (this.stateTree === STATE_ERROR) {
return
+54 -1
View File
@@ -1,7 +1,15 @@
import {describe, it, expect, vi} from 'vitest'
import {describe, it, expect, vi, beforeEach} from 'vitest'
import {GrampsJs} from '../../src/GrampsJs.js'
import {apiGetTokens, createFirstTree} from '../../src/api.js'
import {passwordsMismatch} from '../../src/components/GrampsjsFirstRun.js'
vi.mock('../../src/api.js', async importActual => {
const actual = await importActual()
return {...actual, apiGetTokens: vi.fn(), createFirstTree: vi.fn()}
})
const fakeJwt = claims => `header.${btoa(JSON.stringify(claims))}.signature`
describe('password confirmation', () => {
it('reports nothing while the confirmation is empty', () => {
expect(passwordsMismatch('hunter2', '')).to.equal(false)
@@ -72,3 +80,48 @@ describe('first run onboarding', () => {
)
})
})
describe('first run submit', () => {
const makeElement = () => {
const element = document.createElement('grampsjs-first-run')
element.createRenderRoot()
element.appState = {}
element._submitUser = vi.fn(async () => {
element.stateUser = 3
})
element._submitConfig = vi.fn()
return element
}
beforeEach(() => {
vi.clearAllMocks()
localStorage.clear()
createFirstTree.mockResolvedValue({})
})
it('skips tree creation when the login token has a tree', async () => {
apiGetTokens.mockImplementation(async () => {
localStorage.setItem('access_token', fakeJwt({tree: 'Queen'}))
return {}
})
const element = makeElement()
await element._submit()
expect(createFirstTree).not.toHaveBeenCalled()
expect(element._hasTree).to.equal(true)
})
it('creates the first tree when the login token has no tree', async () => {
apiGetTokens.mockImplementation(async () => {
localStorage.setItem('access_token', fakeJwt({}))
return {}
})
const element = makeElement()
await element._submit()
expect(createFirstTree).toHaveBeenCalledOnce()
expect(element._hasTree).to.equal(false)
})
})