Skip to content

Commit 8391850

Browse files
authored
Add Database tests.
Added tests for Real Time Database (RTDB).
1 parent 27de10a commit 8391850

File tree

10 files changed

+323
-3
lines changed

10 files changed

+323
-3
lines changed

app/page.tsx

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,12 @@ export default async function Page() {
4848
<li><Link href="/tests/auth/web_client">Auth Web SDK client-side tests</Link></li>
4949
<li><Link href="/tests/auth/web_ssr">Auth Web SDK server-side tests</Link></li>
5050
</ul>
51+
<p />
52+
<li>Database</li>
53+
<ul>
54+
<li><Link href="/tests/database/web_client">Auth Web SDK client-side tests</Link></li>
55+
<li><Link href="/tests/database/web_ssr">Auth Web SDK server-side tests</Link></li>
56+
</ul>
5157
</ul>
5258
</>
5359
);

app/tests/auth/lib/test.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
import { deleteApp, initializeApp, initializeServerApp } from 'firebase/app';
1818
import { deleteUser, getAuth, onAuthStateChanged, signInAnonymously, User } from 'firebase/auth';
1919
import { firebaseConfig } from 'lib/firebase';
20-
import { OK, OK_SKIPPED, FAILED } from 'lib/util';
20+
import { OK, OK_SKIPPED, FAILED, sleep } from 'lib/util';
2121

2222
export type TestResults = {
2323
initializeAppResult: string,
@@ -64,7 +64,7 @@ async function authStateChangedUserSignedIn(auth): Promise<User> {
6464
export async function testAuth(isServer: boolean = false): Promise<TestResults> {
6565
const result: TestResults = initializeTestResults();
6666
try {
67-
const firebaseApp = initializeApp(firebaseConfig, "authTest");
67+
const firebaseApp = initializeApp(firebaseConfig);
6868
result.initializeAppResult = OK;
6969
const auth = getAuth(firebaseApp);
7070
await auth.authStateReady();
@@ -97,6 +97,7 @@ export async function testAuth(isServer: boolean = false): Promise<TestResults>
9797
result.deleteServerAppResult = OK;
9898
}
9999
await deleteUser(auth.currentUser);
100+
sleep(500);
100101
if (auth.currentUser === null) {
101102
result.deleteUserResult = OK;
102103
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
/**
2+
* @license
3+
* Copyright 2024 Google LLC
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
'use client'
18+
19+
import { useState, useEffect } from 'react'
20+
import { testDatabase, initializeTestResults } from '../lib/test';
21+
import ResultsDisplay from './results_display';
22+
23+
export default function CsrTestRunner() {
24+
const [testStatus, setTestStatus] = useState<string>("running...");
25+
const [testResults, setTestResults] = useState(initializeTestResults());
26+
useEffect(() => {
27+
const asyncTest = async () => {
28+
setTestResults(await testDatabase());
29+
setTestStatus("Complete!");
30+
}
31+
asyncTest().catch((e) => {
32+
console.error("Error encountered during testing: ", e);
33+
setTestStatus("Errored!");
34+
});
35+
}, []);
36+
37+
return (
38+
<ResultsDisplay statusString={testStatus} testResults={testResults} />
39+
);
40+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/**
2+
* @license
3+
* Copyright 2024 Google LLC
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
import Link from 'next/link';
18+
export default function ResultsDisplay({ statusString, testResults }) {
19+
return (
20+
<>
21+
<h2 title="testStatus">{statusString}</h2>
22+
<h4 title="initializeAppResult">initializeAppResult: {testResults.initializeAppResult}</h4>
23+
<h4 title="initializeDatabaseResult">initializeDatabaseResult: {testResults.initializeDatabaseResult}</h4>
24+
<h4 title="createRefResult">createRefResult: {testResults.createRefResult}</h4>
25+
<h4 title="deleteSetValueListenerResult">deleteSetValueListenerResult: {testResults.deleteSetValueListenerResult}</h4>
26+
<h4 title="deleteUpdateValueListenerResult">deleteUpdateValueListenerResult: {testResults.deleteUpdateValueListenerResult}</h4>
27+
<h4 title="deleteRemoveValueListenerResult">deleteRemoveValueListenerResult: {testResults.deleteRemoveValueListenerResult}</h4>
28+
<h4 title="setValueResult">setValueResult: {testResults.setValueResult}</h4>
29+
<h4 title="updateValueResult">updateValueResult: {testResults.updateValueResult}</h4>
30+
<h4 title="deleteValueResult">deleteValueResult: {testResults.deleteValueResult}</h4>
31+
<h4 title="deleteAppResult">deleteAppResult: {testResults.deleteAppResult}</h4>
32+
<p />
33+
<Link href="/">Back to test index</Link>
34+
</>
35+
);
36+
}

app/tests/database/lib/test.ts

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
/**
2+
* @license
3+
* Copyright 2024 Google LLC
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
import { deleteApp, initializeApp } from 'firebase/app';
19+
import { getDatabase, update, off, onValue, ref, remove, set } from 'firebase/database';
20+
import { firebaseConfig } from 'lib/firebase';
21+
import { OK, OK_SKIPPED, FAILED } from 'lib/util';
22+
23+
export type TestResults = {
24+
initializeAppResult: string,
25+
initializeDatabaseResult: string,
26+
createRefResult: string,
27+
deleteSetValueListenerResult: string,
28+
deleteUpdateValueListenerResult: string,
29+
deleteRemoveValueListenerResult: string,
30+
setValueResult: string,
31+
updateValueResult: string,
32+
deleteValueResult: string,
33+
deleteAppResult: string
34+
};
35+
36+
export function initializeTestResults(): TestResults {
37+
return {
38+
initializeAppResult: FAILED,
39+
initializeDatabaseResult: FAILED,
40+
createRefResult: FAILED,
41+
deleteSetValueListenerResult: FAILED,
42+
deleteUpdateValueListenerResult: FAILED,
43+
deleteRemoveValueListenerResult: FAILED,
44+
setValueResult: FAILED,
45+
updateValueResult: FAILED,
46+
deleteValueResult: FAILED,
47+
deleteAppResult: FAILED
48+
};
49+
}
50+
export async function testDatabase(isServer: boolean = false): Promise<TestResults> {
51+
const result: TestResults = initializeTestResults();
52+
try {
53+
const firebaseApp = initializeApp(firebaseConfig, "authTest");
54+
if (firebaseApp === null) {
55+
return result;
56+
}
57+
result.initializeAppResult = OK;
58+
59+
const db = getDatabase(firebaseApp);
60+
if (db === null) {
61+
return result;
62+
}
63+
result.initializeDatabaseResult = OK;
64+
65+
const dbRef = ref(db, 'abc/def');
66+
if (dbRef === null) {
67+
return result;
68+
}
69+
result.createRefResult = OK;
70+
71+
// Set test.
72+
onValue(dbRef, snap => {
73+
if (snap.exists()) {
74+
const value = snap.val();
75+
if (value.text !== undefined && value.text === 'string 123 xyz') {
76+
result.setValueResult = OK;
77+
}
78+
}
79+
});
80+
await set(dbRef, { text: 'string 123 xyz' });
81+
off(dbRef);
82+
result.deleteSetValueListenerResult = OK;
83+
84+
// Update test.
85+
onValue(dbRef, snap => {
86+
if (snap.exists()) {
87+
const value = snap.val();
88+
if (value.number !== undefined && value.number === 987) {
89+
result.updateValueResult = OK;
90+
}
91+
}
92+
});
93+
await update(dbRef, { number: 987 });
94+
off(dbRef);
95+
result.deleteUpdateValueListenerResult = OK;
96+
97+
// Remove test.
98+
onValue(dbRef, snap => {
99+
if (!snap.exists()) {
100+
result.deleteValueResult = OK;
101+
}
102+
});
103+
await remove(dbRef);
104+
console.log("remove returned");
105+
off(dbRef);
106+
107+
result.deleteRemoveValueListenerResult = OK;
108+
109+
// Note: Deleting the app hangs the SSR pass on playwright on Firefox
110+
// and Chromium, but the hang does not occur when manually testing with
111+
// those browsers.
112+
if (isServer) {
113+
result.deleteAppResult = OK_SKIPPED;
114+
} else {
115+
deleteApp(firebaseApp);
116+
result.deleteAppResult = OK;
117+
}
118+
} catch (e) {
119+
console.log("Caught error: ", e);
120+
}
121+
return result;
122+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
/**
2+
* @license
3+
* Copyright 2024 Google LLC
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
import type { Metadata } from 'next'
18+
import CSRTestRunner from '../components/csr_test_runner';
19+
20+
export const metadata: Metadata = {
21+
title: 'Database Web SDK CSR test'
22+
}
23+
24+
export default function Page() {
25+
return (
26+
<>
27+
<h1>Database CSR Test results:</h1>
28+
<CSRTestRunner />
29+
</>
30+
);
31+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/**
2+
* @license
3+
* Copyright 2024 Google LLC
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
import type { Metadata } from 'next'
18+
import { testDatabase, TestResults } from '../lib/test';
19+
import ResultsDisplay from '../components/results_display';
20+
21+
// Suppress static site generation as this hangs on the app deletion in test.ts.
22+
export const dynamic = "force-dynamic";
23+
24+
export const metadata: Metadata = {
25+
title: 'Database Web SDK SSR test'
26+
}
27+
28+
export default async function Page() {
29+
const testResults: TestResults = await testDatabase(/*isServer=*/true);
30+
return (
31+
<>
32+
<h1>Database SSR Test results:</h1>
33+
<ResultsDisplay statusString='Tests Complete!' testResults={testResults} />
34+
</>
35+
);
36+
}

playwright.config.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ const baseURL = `http://localhost:${PORT}`;
2929
export default defineConfig({
3030
testDir: './tests',
3131
/* Run tests in files in parallel */
32-
fullyParallel: true,
32+
fullyParallel: false,
3333
/* Fail the build on CI if you accidentally left test.only in the source code. */
3434
forbidOnly: !!process.env.CI,
3535
/* Retry on CI only */

tests/auth.spec.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
*/
1717
import { test, expect } from '@playwright/test';
1818

19+
test.describe.configure({ mode: 'serial' });
20+
1921
async function commonExpectations(page) {
2022
await expect(page.getByTitle('initializeAppResult')).not.toContainText("FAILED");
2123
await expect(page.getByTitle('initializeAuthResult')).not.toContainText("FAILED");

tests/database.spec.ts

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
/**
2+
* @license
3+
* Copyright 2024 Google LLC
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
import { test, expect } from '@playwright/test';
18+
19+
test.describe.configure({ mode: 'serial' });
20+
21+
async function commonExpectations(page) {
22+
await expect(page.getByTitle('initializeAppResult')).not.toContainText("FAILED");
23+
await expect(page.getByTitle('initializeDatabaseResult')).not.toContainText("FAILED");
24+
await expect(page.getByTitle('createRefResult')).not.toContainText("FAILED");
25+
await expect(page.getByTitle('deleteSetValueListenerResult')).not.toContainText("FAILED");
26+
await expect(page.getByTitle('deleteUpdateValueListenerResult')).not.toContainText("FAILED");
27+
await expect(page.getByTitle('deleteRemoveValueListenerResult')).not.toContainText("FAILED");
28+
await expect(page.getByTitle('setValueResult')).not.toContainText("FAILED");
29+
await expect(page.getByTitle('updateValueResult')).not.toContainText("FAILED");
30+
await expect(page.getByTitle('deleteValueResult')).not.toContainText("FAILED");
31+
await expect(page.getByTitle('deleteAppResult')).not.toContainText("FAILED");
32+
}
33+
34+
test('database operations should pass - client', async ({ page, baseURL }) => {
35+
await page.goto(`${baseURL}/tests/database/web_client`);
36+
await expect(page.getByTitle('testStatus')).toContainText('Complete', { timeout: 10000 });
37+
await expect(page.locator('h1')).toContainText('Database CSR Test');
38+
await commonExpectations(page);
39+
});
40+
41+
test('database operations should pass - server', async ({ page, baseURL }) => {
42+
await page.goto(`${baseURL}/tests/database/web_ssr`);
43+
await expect(page.getByTitle('testStatus')).toContainText('Complete', { timeout: 10000 });
44+
await expect(page.locator('h1')).toContainText('Database SSR Test');
45+
await commonExpectations(page);
46+
});

0 commit comments

Comments
 (0)