daml/templates/create-daml-app-test-resources/messaging.patch
Rohan Jacob-Rao 37ca4af529
create-daml-app: Add end-to-end tests to integration tests (#5540)
This PR gets yarn test running the Puppeteer end-to-end tests in the GSG integration test.

The first step of the test is adding the extra dependencies (Jest, Puppeteer and more). The GSG recommends a yarn add command, but this does not work against HEAD. This is because yarn add does not use resolutions in the parent package.json, and then complains about unknown versions 0.0.0 of the daml TS libaries. The solution here is to hack in the extra dependencies into the ui/package.json and then yarn install. This works, but it hard codes version numbers which we would need to maintain. I would like to be able to say version "latest", which is what yarn add would install.

The next step of the test is to copy the index.test.ts file and run yarn test in CI mode.

I've moved the GSG test to a new create-daml-app-tests target. It's marked "exclusive" in Bazel until we figure out how to avoid hardcoding port numbers. This is a bit tricky since the HTTP port is hardcoded in a couple of places in ui/package.json.

Finally, this PR gets the GSG testing docs to reference the code in the new templates/create-daml-app-test-resources folder.

changelog_begin
changelog_end
2020-04-17 12:42:24 -04:00

175 lines
5.8 KiB
Diff

diff --git templates/create-daml-app/daml/User.daml templates/create-daml-app/daml/User.daml
--- templates/create-daml-app/daml/User.daml
+++ templates/create-daml-app/daml/User.daml
@@ -25,3 +25,22 @@ template User with
archive self
create this with following = userToFollow :: following
-- FOLLOW_END
+
+ -- SENDMESSAGE_BEGIN
+ nonconsuming choice SendMessage: ContractId Message with
+ sender: Party
+ content: Text
+ controller sender
+ do
+ assertMsg "Designated user must follow you back to send a message" (elem sender following)
+ create Message with sender, receiver = username, content
+ -- SENDMESSAGE_END
+
+-- MESSAGE_BEGIN
+template Message with
+ sender: Party
+ receiver: Party
+ content: Text
+ where
+ signatory sender, receiver
+-- MESSAGE_END
diff --git templates/create-daml-app/ui/src/components/MainView.tsx templates/create-daml-app/ui/src/components/MainView.tsx
--- templates/create-daml-app/ui/src/components/MainView.tsx
+++ templates/create-daml-app/ui/src/components/MainView.tsx
@@ -8,6 +8,10 @@ import { User } from '@daml.js/create-daml-app';
import { useParty, useLedger, useStreamFetchByKey, useStreamQuery } from '@daml/react';
import UserList from './UserList';
import PartyListEdit from './PartyListEdit';
+// IMPORTS_BEGIN
+import MessageEdit from './MessageEdit';
+import MessageList from './MessageList';
+// IMPORTS_END
// USERS_BEGIN
const MainView: React.FC = () => {
@@ -78,6 +82,22 @@ const MainView: React.FC = () => {
/>
{/* USERLIST_END */}
</Segment>
+ {/* MESSAGES_SEGMENT_BEGIN */}
+ <Segment>
+ <Header as='h2'>
+ <Icon name='pencil square' />
+ <Header.Content>
+ Messages
+ <Header.Subheader>Send a message to a follower</Header.Subheader>
+ </Header.Content>
+ </Header>
+ <MessageEdit
+ followers={followers.map(follower => follower.username)}
+ />
+ <Divider />
+ <MessageList />
+ </Segment>
+ {/* MESSAGES_SEGMENT_END */}
</Grid.Column>
</Grid.Row>
</Grid>
diff --git templates/create-daml-app/ui/src/components/MessageEdit.tsx templates/create-daml-app/ui/src/components/MessageEdit.tsx
--- /dev/null
+++ templates/create-daml-app/ui/src/components/MessageEdit.tsx
@@ -0,0 +1,70 @@
+// Copyright (c) 2020 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
+// SPDX-License-Identifier: Apache-2.0
+
+// MESSAGEEDIT_BEGIN
+import React from 'react'
+import { Form, Button } from 'semantic-ui-react';
+import { Party } from '@daml/types';
+import { User } from '@daml.js/create-daml-app';
+import { useParty, useLedger } from '@daml/react';
+
+type Props = {
+ followers: Party[];
+}
+
+/**
+ * React component to edit a message to send to a follower.
+ */
+const MessageEdit: React.FC<Props> = ({followers}) => {
+ const sender = useParty();
+ const [receiver, setReceiver] = React.useState<string | undefined>();
+ const [content, setContent] = React.useState("");
+ const [isSubmitting, setIsSubmitting] = React.useState(false);
+ const ledger = useLedger();
+
+ const submitMessage = async (event: React.FormEvent) => {
+ try {
+ event.preventDefault();
+ if (receiver === undefined) {
+ return;
+ }
+ setIsSubmitting(true);
+ await ledger.exerciseByKey(User.User.SendMessage, receiver, {sender, content});
+ setContent("");
+ } catch (error) {
+ alert(`Error sending message:\n${JSON.stringify(error)}`);
+ } finally {
+ setIsSubmitting(false);
+ }
+ };
+
+ return (
+ <Form onSubmit={submitMessage}>
+ <Form.Dropdown
+ selection
+ className='test-select-message-receiver'
+ placeholder="Select a follower"
+ options={followers.map(follower => ({ key: follower, text: follower, value: follower }))}
+ value={receiver}
+ onChange={event => setReceiver(event.currentTarget.textContent ?? undefined)}
+ />
+ <Form.Input
+ className='test-select-message-content'
+ placeholder="Write a message"
+ value={content}
+ onChange={event => setContent(event.currentTarget.value)}
+ />
+ <Button
+ fluid
+ className='test-select-message-send-button'
+ type="submit"
+ disabled={isSubmitting || receiver === undefined || content === ""}
+ loading={isSubmitting}
+ content="Send"
+ />
+ </Form>
+ );
+};
+
+export default MessageEdit;
+// MESSAGEEDIT_END
diff --git templates/create-daml-app/ui/src/components/MessageList.tsx templates/create-daml-app/ui/src/components/MessageList.tsx
--- /dev/null
+++ templates/create-daml-app/ui/src/components/MessageList.tsx
@@ -0,0 +1,33 @@
+// Copyright (c) 2020 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
+// SPDX-License-Identifier: Apache-2.0
+
+// MESSAGELIST_BEGIN
+import React from 'react'
+import { List, ListItem } from 'semantic-ui-react';
+import { User } from '@daml.js/create-daml-app';
+import { useStreamQuery } from '@daml/react';
+
+/**
+ * React component displaying the list of messages for the current user.
+ */
+const MessageList: React.FC = () => {
+ const messagesResult = useStreamQuery(User.Message);
+
+ return (
+ <List relaxed>
+ {messagesResult.contracts.map(message => {
+ const {sender, receiver, content} = message.payload;
+ return (
+ <ListItem
+ className='test-select-message-item'
+ key={message.contractId}>
+ <strong>{sender} &rarr; {receiver}:</strong> {content}
+ </ListItem>
+ );
+ })}
+ </List>
+ );
+};
+
+export default MessageList;
+// MESSAGELIST_END