Skip to content

Commit

Permalink
Merge pull request #57 from art-by-city/53-limit-curation-title-tag-t…
Browse files Browse the repository at this point in the history
…o-150-chars

Limits title tag to 150 chars & adds curation modules spec tests
  • Loading branch information
jim-toth committed Oct 19, 2023
2 parents b6964ca + c39bc08 commit 42a91d4
Show file tree
Hide file tree
Showing 5 changed files with 188 additions and 18 deletions.
9 changes: 5 additions & 4 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@
"opener": "^1.5.2",
"rimraf": "^5.0.1",
"selenium-webdriver": "^4.11.1",
"sinon": "^15.2.0",
"sinon": "^16.1.1",
"sinon-chai": "^3.7.0",
"ts-loader": "^9.4.4",
"ts-node": "^10.9.1",
Expand Down
34 changes: 21 additions & 13 deletions src/curation/authenticated.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export default class AuthenticatedArtByCityCurations
super(arweave, warp, config)
}

private determineCurationType(
private determineCurationSource(
type: CurationType
): { srcTxId: string, contractName: string } {
switch (type) {
Expand Down Expand Up @@ -66,6 +66,16 @@ export default class AuthenticatedArtByCityCurations
const addressWhitelist = opts.addressWhitelist || []
const roles = opts.roles || { curator: [] }

// NB: Copy full description to curation state metadata
if (opts.description) {
base.metadata['description'] = opts.description
}

// NB: Copy topic to curation state metadata
if (opts.topic) {
base.metadata['topic'] = opts.topic
}

if (type === 'ownable') {
return base
}
Expand All @@ -86,34 +96,32 @@ export default class AuthenticatedArtByCityCurations
}

async create(type: CurationType, opts: CurationCreationOptions) {
const { srcTxId, contractName } = this.determineCurationType(type)
const { srcTxId, contractName } = this.determineCurationSource(type)
const initialState = this.createInitialState(type, opts)
const tags: Tag[] = [
const tags = (opts.tags || []).map<Tag>(tag => new Tag(tag.name, tag.value))

tags.push(
new Tag('Contract-Name', contractName),

// ArtByCity / ArFS Entity-Type
new Tag('Entity-Type', 'curation'),

// ANS-110 Title & Type
new Tag('Title', opts.title),
new Tag('Type', 'curation')
]
// ANS-110 Type
new Tag('Type', 'curation'),

// ANS-110 Title
new Tag('Title', opts.title.substring(0, 150))
)

// ANS-110 Description
if (opts.description) {
// NB: Description tag has a limit of 300 chars
tags.push(new Tag('Description', opts.description.substring(0, 300)))

// NB: Copy full description to curation state metadata
initialState.metadata['description'] = opts.description
}

// ANS-110 Topic
if (opts.topic) {
tags.push(new Tag('Topic', opts.topic))

// NB: Copy topic to curation state metadata
initialState.metadata['topic'] = opts.topic
}

const { contractTxId } = await this.warp.deployFromSourceTx({
Expand Down
1 change: 1 addition & 0 deletions src/curation/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ export interface CurationCreationOptions {
roles?: {
curator: []
}
tags?: { name: string, value: string }[]
}

export { default as ArtByCityCurations } from './curation'
Expand Down
160 changes: 160 additions & 0 deletions test/spec/curation.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
import 'mocha'
import { expect } from 'chai'
import sinon from 'sinon'
import Arweave from 'arweave'
import { Warp } from 'warp-contracts'

import { AuthenticatedArtByCityCurations } from '../../src/curation'
import { ArtByCityConfig } from '../../src'

const MOCK_OWNER = '0x-mock-owner'
const MOCK_CONTRACT_TX_ID = 'mock-contract-tx-id'
const MOCK_ABC_CONFIG: ArtByCityConfig = {
environment: 'development',
contracts: {
usernames: 'mock-usernames-contract-id',
curation: {
ownable: 'mock-ownable-curation-contract-src-id',
whitelist: 'mock-whitelist-curation-contract-src-id',
collaborative: 'mock-collaborative-curation-contract-src-id',
collaborativeWhitelist:
'mock-collaborative-whitelist-curation-contract-src-id'
}
},
cache: {
type: 'memcache'
}
}

const warpMock = sinon.createStubInstance(Warp)
const arweaveMock = sinon.createStubInstance(Arweave)
let authenticatedCurations: AuthenticatedArtByCityCurations

describe('Curation Module', () => {
beforeEach(() => {
authenticatedCurations = new AuthenticatedArtByCityCurations(
arweaveMock,
warpMock,
MOCK_ABC_CONFIG,
'use_wallet'
)
warpMock.deployFromSourceTx.resolves({
contractTxId: MOCK_CONTRACT_TX_ID
})
})

afterEach(() => {
sinon.reset()
})

context('Unauthenticated Curation Module', () => {
it('constructs')
it('gets curation by id')
it('queries curations by creator')
})

context('Authenticated Curation Module', () => {
it('creates ownable curations', async () => {
const curationId = await authenticatedCurations.create('ownable', {
owner: MOCK_OWNER,
title: 'My Ownable Curation'
})

expect(curationId).to.equal(MOCK_CONTRACT_TX_ID)
expect(warpMock.deployFromSourceTx.calledOnce).to.be.true
const contractData = warpMock.deployFromSourceTx.firstCall.args[0]
expect(contractData.srcTxId).to.equal(
MOCK_ABC_CONFIG.contracts.curation.ownable
)
expect(
(contractData.tags || []).some(tag => {
return tag.get('name') === 'Contract-Name'
&& tag.get('value') === 'Ownable-Curation-Contract'
})
).to.be.true
})

it('creates whitelist curations', async () => {
const curationId = await authenticatedCurations.create('whitelist', {
owner: MOCK_OWNER,
title: 'My Whitelist Curation'
})

expect(curationId).to.equal(MOCK_CONTRACT_TX_ID)
expect(warpMock.deployFromSourceTx.calledOnce).to.be.true
const contractData = warpMock.deployFromSourceTx.firstCall.args[0]
expect(contractData.srcTxId).to.equal(
MOCK_ABC_CONFIG.contracts.curation.whitelist
)
expect(
(contractData.tags || []).some(tag => {
return tag.get('name') === 'Contract-Name'
&& tag.get('value') === 'Whitelist-Curation-Contract'
})
).to.be.true
})

it('creates collaborative curations', async () => {
const curationId = await authenticatedCurations.create('collaborative', {
owner: MOCK_OWNER,
title: 'My Collaborative Curation'
})

expect(curationId).to.equal(MOCK_CONTRACT_TX_ID)
expect(warpMock.deployFromSourceTx.calledOnce).to.be.true
const contractData = warpMock.deployFromSourceTx.firstCall.args[0]
expect(contractData.srcTxId).to.equal(
MOCK_ABC_CONFIG.contracts.curation.collaborative
)
expect(
(contractData.tags || []).some(tag => {
return tag.get('name') === 'Contract-Name'
&& tag.get('value') === 'Collaborative-Curation-Contract'
})
).to.be.true
})

it('creates collaborative whitelist curations', async () => {
const curationId = await authenticatedCurations.create(
'collaborative-whitelist',
{
owner: MOCK_OWNER,
title: 'My Collaborative Whitelist Curation'
}
)

expect(curationId).to.equal(MOCK_CONTRACT_TX_ID)
expect(warpMock.deployFromSourceTx.calledOnce).to.be.true
const contractData = warpMock.deployFromSourceTx.firstCall.args[0]
expect(contractData.srcTxId).to.equal(
MOCK_ABC_CONFIG.contracts.curation.collaborativeWhitelist
)
expect(
(contractData.tags || []).some(tag => {
return tag.get('name') === 'Contract-Name'
&& tag.get('value') === 'Collaborative-Whitelist-Curation-Contract'
})
).to.be.true
})

it('limits ANS-110 title to 150 chars and desc to 300 chars', async () => {
const title = 'My Curation'.padEnd(175)
const description = 'My Curation'.padEnd(350)

await authenticatedCurations.create('ownable', {
owner: MOCK_OWNER,
title,
description
})

const { tags } = warpMock.deployFromSourceTx.firstCall.args[0]
const titleTag = (tags || []).find(tag => tag.get('name') === 'Title')
const descTag = (tags || []).find(
tag => tag.get('name') === 'Description'
)

expect(titleTag?.get('value')).to.equal(title.substring(0, 150))
expect(descTag?.get('value')).to.equal(description.substring(0, 300))
})
})
})

0 comments on commit 42a91d4

Please sign in to comment.