When I try to test a component that does things like store data in firestore or read data, I get the error FirebaseError: projectId must be a string in FirebaseApp.options
.
I'm thinking that this error is probably not a problem with projectId, but I have no idea what is wrong.
The error log looks like this.
FAIL src/components/__tests__/Login.test.tsx
● Test suite failed to run
FirebaseError: projectId must be a string in FirebaseApp.options
14 | });
15 |
> 16 | export const db = firebase.firestore();
| ^
17 | export const auth = app.auth();
18 | export const timestamp = firebase.firestore.FieldValue.serverTimestamp();
19 | export default app;
Here is my test code and the code for the component.
export default function Login() {
const classes = useStyles();
const emailRef = useRef();
const passwordRef = useRef();
const { login }: any = useAuth();
const [error, setError] = useState("");
const [loading, setLoading] = useState(false);
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const history = useHistory();
const inputEmail = useCallback(
(event) => {
setEmail(event.target.value);
},
[setEmail]
);
const inputPassword = useCallback(
(event) => {
setPassword(event.target.value);
},
[setPassword]
);
async function handleSubmit(e: any) {
e.preventDefault();
setError("");
setLoading(true);
return login(email, password)
.then(() => {
history.push("/");
})
.catch((error: any) => {
setError("failed!!");
})
.finally(() => {
setLoading(false);
});
}
const onClickGuestButton = () => {
setError("");
setLoading(true);
return login("guest@example.com", "password")
.then(() => {
history.push("/");
})
.catch((error: any) => {
setError("failed!!");
})
.finally(() => {
setLoading(false);
});
};
return (
<>
{error && <Alert severity="error">{error}</Alert>}
<Container component="main" maxWidth="xs">
<div className={classes.paper}>
<Avatar className={classes.avatar}>
<LockOutlinedIcon />
</Avatar>
<Typography component="h1" variant="h5">
Login
</Typography>
<form className={classes.form} noValidate onSubmit={handleSubmit}>
<TextField
variant="outlined"
margin="normal"
required
fullWidth
id="email"
label="Email Address"
value={email}
inputRef={emailRef}
onChange={inputEmail}
/>
<TextField
variant="outlined"
margin="normal"
required
fullWidth
label="Password"
type="password"
id="password"
value={password}
inputRef={passwordRef}
onChange={inputPassword}
/>
<FormControlLabel
control={<Checkbox value="remember" color="primary" />}
label="Remember me"
/>
<Button
type="submit"
fullWidth
variant="contained"
color="primary"
className={classes.submit}
disabled={loading}
>
Login
</Button>
<Grid container>
<Grid item xs>
<Link to="/forgot-password">
forget password?
</Link>
</Grid>
<Grid item>
<Link to="/signup">{"signup"}</Link>
</Grid>
</Grid>
</form>
</div>
</Container>
<Button className={classes.guestLogin} onClick={onClickGuestButton}>
Login as guest
</Button>
</>
);
}
import * as React from "react";
import Login from "../Login";
import { configure, mount, shallow } from "enzyme";
import Adapter from "enzyme-adapter-react-16";
import ReactDOM, * as ReactDom from "react-dom";
configure({ adapter: new Adapter() });
describe("Login", () => {
it("renders without crashing", () => {
console.error = jest.fn();
const div = document.createElement("div");
ReactDOM.render(<Login />, div);
ReactDOM.unmountComponentAtNode(div);
expect(console.error).not.toHaveBeenCalled();
});
});
I've heard that it's better to use mock when testing components that communicate with APIs such as firebase, but I'm not sure how to use it.
I also don't know if I should use mock or not in this case.
By the way, of course, if you test the <Login />
component without importing it, the test will pass. Also, not only the component, but also another component will cause a FirebaseError if firebase is used.
Do you have any good ideas?
Did you ever find a solution to this? I have the exact same issue.
RépondreSupprimer