Page Menu
Home
WickedGov Phorge
Search
Configure Global Search
Log In
Files
F1429115
Creation.js
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Size
8 KB
Referenced Files
None
Subscribers
None
Creation.js
View Options
'use strict'
;
const
{
action
,
assert
,
REST
,
utils
}
=
require
(
'api-testing'
);
const
supertest
=
require
(
'supertest'
);
let
pathPrefix
=
'rest.php/content/v1'
;
describe
(
'POST /page'
,
()
=>
{
let
client
,
mindy
,
anon
,
anonToken
;
beforeEach
(
async
()
=>
{
// Reset the client and token before each test
// In a temp account context, making an anonymous edit generates an account
// so we want to reset state after each edit
mindy
=
await
action
.
mindy
();
client
=
new
REST
(
pathPrefix
);
anon
=
await
action
.
getAnon
();
anonToken
=
await
anon
.
token
();
}
);
const
checkEditResponse
=
function
(
title
,
reqBody
,
body
)
{
assert
.
containsAllKeys
(
body
,
[
'title'
,
'key'
,
'source'
,
'latest'
,
'id'
,
'license'
,
'content_model'
]
);
assert
.
containsAllKeys
(
body
.
latest
,
[
'id'
,
'timestamp'
]
);
assert
.
nestedPropertyVal
(
body
,
'source'
,
reqBody
.
source
);
assert
.
nestedPropertyVal
(
body
,
'title'
,
title
);
assert
.
nestedPropertyVal
(
body
,
'key'
,
utils
.
dbkey
(
title
)
);
assert
.
isAbove
(
body
.
latest
.
id
,
0
);
if
(
reqBody
.
content_model
)
{
assert
.
nestedPropertyVal
(
body
,
'content_model'
,
reqBody
.
content_model
);
}
};
const
checkSourceResponse
=
function
(
title
,
reqBody
,
body
)
{
if
(
reqBody
.
content_model
)
{
assert
.
nestedPropertyVal
(
body
,
'content_model'
,
reqBody
.
content_model
);
}
assert
.
nestedPropertyVal
(
body
,
'title'
,
title
);
assert
.
nestedPropertyVal
(
body
,
'key'
,
utils
.
dbkey
(
title
)
);
assert
.
nestedPropertyVal
(
body
,
'source'
,
reqBody
.
source
);
};
describe
(
'successful operation'
,
()
=>
{
it
(
'should create a page if it does not exist'
,
async
()
=>
{
const
titleSuffix
=
utils
.
title
();
const
title
=
'A B+C:D@E-'
+
titleSuffix
;
const
normalizedTitle
=
utils
.
dbkey
(
title
);
// In "title style" encoding, spaces turn to underscores,
// colons are preserved, and slashes and pluses get encoded.
// FIXME: correct handling of encoded slashes depends on
// the server setup and can't be tested reliably.
const
encodedTitle
=
'A_B%2BC:D@E-'
+
titleSuffix
;
const
reqBody
=
{
token
:
anonToken
,
source
:
'Lörem Ipsüm'
,
comment
:
'tästing'
,
title
};
const
{
status
:
editStatus
,
body
:
editBody
,
header
}
=
await
client
.
post
(
'/page'
,
reqBody
);
assert
.
equal
(
editStatus
,
201
);
assert
.
match
(
header
[
'content-type'
],
/^application\/json/
);
assert
.
nestedProperty
(
header
,
'location'
);
const
location
=
header
.
location
;
assert
.
match
(
location
,
new
RegExp
(
`^https?://.*/v1/page/
${
encodedTitle
}
$`
)
);
checkEditResponse
(
title
,
reqBody
,
editBody
);
// follow redirect
const
{
status
:
redirStatus
,
body
:
redirBody
,
header
:
redirHeader
}
=
await
supertest
.
agent
(
location
).
get
(
''
);
assert
.
equal
(
redirStatus
,
200
);
assert
.
match
(
redirHeader
[
'content-type'
],
/^application\/json/
);
checkSourceResponse
(
title
,
reqBody
,
redirBody
);
// construct request to fetch content
const
{
status
:
sourceStatus
,
body
:
sourceBody
,
header
:
sourceHeader
}
=
await
client
.
get
(
`/page/
${
normalizedTitle
}
`
);
assert
.
equal
(
sourceStatus
,
200
);
assert
.
match
(
sourceHeader
[
'content-type'
],
/^application\/json/
);
checkSourceResponse
(
title
,
reqBody
,
sourceBody
);
}
);
it
(
'should create a page with specified model'
,
async
()
=>
{
const
title
=
utils
.
title
(
'Edit Test '
);
const
normalizedTitle
=
utils
.
dbkey
(
title
);
// TODO: Test with a model different from the default. This however requires
// the changecontentmodel permission, which anons don't have.
const
reqBody
=
{
token
:
anonToken
,
source
:
'Lörem Ipsüm'
,
comment
:
'tästing'
,
content_model
:
'wikitext'
,
title
};
const
{
status
:
editStatus
,
body
:
editBody
,
header
:
editHeader
}
=
await
client
.
post
(
'/page'
,
reqBody
);
assert
.
equal
(
editStatus
,
201
);
assert
.
match
(
editHeader
[
'content-type'
],
/^application\/json/
);
checkEditResponse
(
title
,
reqBody
,
editBody
);
const
{
status
:
sourceStatus
,
body
:
sourceBody
,
header
:
sourceHeader
}
=
await
client
.
get
(
`/page/
${
normalizedTitle
}
`
);
assert
.
equal
(
sourceStatus
,
200
);
assert
.
match
(
sourceHeader
[
'content-type'
],
/^application\/json/
);
checkSourceResponse
(
title
,
reqBody
,
sourceBody
);
}
);
}
);
describe
(
'request validation'
,
()
=>
{
const
requiredProps
=
[
'source'
,
'comment'
,
'title'
];
requiredProps
.
forEach
(
(
missingPropName
)
=>
{
const
title
=
utils
.
title
(
'Edit Test '
);
const
reqBody
=
{
token
:
anonToken
,
source
:
'Lörem Ipsüm'
,
comment
:
'tästing'
,
title
};
it
(
`should fail when
${
missingPropName
}
is missing from the request body`
,
async
()
=>
{
const
incompleteBody
=
{
...
reqBody
};
delete
incompleteBody
[
missingPropName
];
const
{
status
:
editStatus
,
body
:
editBody
,
header
:
editHeader
}
=
await
client
.
post
(
'/page'
,
incompleteBody
);
assert
.
equal
(
editStatus
,
400
);
assert
.
match
(
editHeader
[
'content-type'
],
/^application\/json/
);
assert
.
nestedProperty
(
editBody
,
'messageTranslations'
);
}
);
}
);
it
(
'should fail if no token is given'
,
async
()
=>
{
const
title
=
utils
.
title
(
'Edit Test '
);
const
reqBody
=
{
// no token
source
:
'Lörem Ipsüm'
,
comment
:
'tästing'
,
title
};
const
{
status
:
editStatus
,
body
:
editBody
,
header
:
editHeader
}
=
await
client
.
post
(
'/page'
,
reqBody
);
assert
.
equal
(
editStatus
,
403
);
assert
.
match
(
editHeader
[
'content-type'
],
/^application\/json/
);
assert
.
nestedProperty
(
editBody
,
'messageTranslations'
);
}
);
it
(
'should fail if a bad token is given'
,
async
()
=>
{
const
title
=
utils
.
title
(
'Edit Test '
);
const
reqBody
=
{
token
:
'BAD'
,
source
:
'Lörem Ipsüm'
,
comment
:
'tästing'
,
title
};
const
{
status
:
editStatus
,
body
:
editBody
,
header
:
editHeader
}
=
await
client
.
post
(
'/page'
,
reqBody
);
assert
.
equal
(
editStatus
,
403
);
assert
.
match
(
editHeader
[
'content-type'
],
/^application\/json/
);
assert
.
nestedProperty
(
editBody
,
'messageTranslations'
);
}
);
it
(
'should fail if a bad content model is given'
,
async
()
=>
{
const
title
=
utils
.
title
(
'Edit Test '
);
const
reqBody
=
{
token
:
anonToken
,
source
:
'Lörem Ipsüm'
,
comment
:
'tästing'
,
content_model
:
'THIS DOES NOT EXIST!'
,
title
};
const
{
status
:
editStatus
,
body
:
editBody
,
header
:
editHeader
}
=
await
client
.
post
(
'/page'
,
reqBody
);
assert
.
equal
(
editStatus
,
400
);
assert
.
match
(
editHeader
[
'content-type'
],
/^application\/json/
);
assert
.
nestedProperty
(
editBody
,
'messageTranslations'
);
}
);
it
(
'should fail if a bad title is given'
,
async
()
=>
{
const
title
=
'_|_'
;
// not a valid page title
const
reqBody
=
{
token
:
anonToken
,
source
:
'Lörem Ipsüm'
,
comment
:
'tästing'
,
title
};
const
{
status
:
editStatus
,
body
:
editBody
,
header
:
editHeader
}
=
await
client
.
post
(
'/page'
,
reqBody
);
assert
.
equal
(
editStatus
,
400
);
assert
.
match
(
editHeader
[
'content-type'
],
/^application\/json/
);
assert
.
nestedProperty
(
editBody
,
'messageTranslations'
);
}
);
}
);
describe
(
'failures due to system state'
,
()
=>
{
it
(
'should detect a conflict if page exist'
,
async
()
=>
{
const
title
=
utils
.
title
(
'Edit Test '
);
// create
await
mindy
.
edit
(
title
,
{}
);
const
reqBody
=
{
token
:
anonToken
,
source
:
'Lörem Ipsüm'
,
comment
:
'tästing'
,
title
};
const
{
status
:
editStatus
,
body
:
editBody
,
header
:
editHeader
}
=
await
client
.
post
(
'/page'
,
reqBody
);
assert
.
equal
(
editStatus
,
409
);
assert
.
match
(
editHeader
[
'content-type'
],
/^application\/json/
);
assert
.
nestedProperty
(
editBody
,
'messageTranslations'
);
}
);
}
);
describe
(
'permission checks'
,
()
=>
{
it
(
'should fail when trying to create a protected title without appropriate permissions'
,
async
()
=>
{
const
title
=
utils
.
title
(
'Edit Test '
);
// protected a non-existing title against creation
await
mindy
.
action
(
'protect'
,
{
title
,
token
:
await
mindy
.
token
(),
protections
:
'create=sysop'
},
'POST'
);
const
reqBody
=
{
token
:
anonToken
,
source
:
'Lörem Ipsüm'
,
comment
:
'tästing'
,
title
};
const
{
status
:
editStatus
,
body
:
editBody
,
header
:
editHeader
}
=
await
client
.
post
(
'/page'
,
reqBody
);
assert
.
equal
(
editStatus
,
403
);
assert
.
match
(
editHeader
[
'content-type'
],
/^application\/json/
);
assert
.
nestedProperty
(
editBody
,
'messageTranslations'
);
}
);
}
);
}
);
// eslint-disable-next-line mocha/no-exports
exports
.
init
=
function
(
pp
)
{
// Allow testing both legacy and module paths using the same tests
pathPrefix
=
pp
;
};
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sat, May 16, 17:05 (10 h, 55 m)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
3e/5d/a3221ddc35914e0add5975ff979f
Default Alt Text
Creation.js (8 KB)
Attached To
Mode
rMWPROD MediaWiki Production
Attached
Detach File
Event Timeline
Log In to Comment