diff --git a/src/components/GrampsjsFirstRun.js b/src/components/GrampsjsFirstRun.js
index 2e234555..7c7415eb 100644
--- a/src/components/GrampsjsFirstRun.js
+++ b/src/components/GrampsjsFirstRun.js
@@ -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) {
{
+ 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)
+ })
+})